Node Guide

Menu
Menu

Cookies

Cookies and Statelessness

HTTP is a stateless protocol, which means that it doesn't inherently maintain any memory of previous interactions between the client (browser) and the server. Each request made by the client is treated as an independent transaction, unrelated to any previous requests.

This statelessness poses a challenge when web applications require maintaining user-specific information or session data across multiple requests. For example, consider a scenario where a user logs into a website and expects to stay authenticated as they navigate through different pages. Without any means of maintaining state, the server would have no way of recognizing the user's authentication status on subsequent requests.

Cookies play a crucial role in addressing the stateless problem by providing a mechanism for maintaining stateful interactions. When a server sets a cookie in the browser, it effectively stores a piece of information on the user's device. This information is then sent back to the server with subsequent requests, allowing the server to identify and recognize the user, retrieve session data, and maintain personalized experiences.

By utilizing cookies, web developers can overcome the stateless nature of the HTTP protocol and enable stateful interactions between the client and the server. Cookies serve as a means of preserving user-specific information, session management, and personalized experiences within the otherwise stateless web environment.

Adding Cookies to a Node/Express Application

Adding cookie support to a Node.js/Express application involves installing the necessary middleware and configuring it within your application.

First install the cookie-parser package:

npm install cookie-parser

Import the modules in your application entry file:

Add the middleware to the application with:

This middleware parses the cookies sent by the client and attaches them to the req.cookies object in subsequent middleware and route handlers.

You can now access and manipulate cookies in your routes and middleware using the req.cookies object.

For example, to set a cookie, you can use the res.cookie() method:

To read a cookie, you can access it through the req.cookies object:

To clear a cookie, you can use the res.clearCookie() method:

Exploring the Sample Application

To see cookies in action we will take a break from the films application under development and have a look at cookies in isolation. Clone this repo into a new project.

In the example we will use cookies to store a user's favourite colour and count how many times they have visited a page.

Ensure once cloned you run:

npm install

... and launch the application with:

npm start dev

Notice the entry file src/app.ts has the required set up for cookie.parser outlined above.

Viewing Cookies in the Browser

Using the Chrome Developer Console, you can inspect and manage cookies, view their values, edit or delete specific cookies, and observe how they change as you interact with the website or web application. This can be helpful for debugging, troubleshooting, or understanding the behavior of cookies in your web development projects.

Right-click anywhere on the page and select "Inspect" or press Ctrl+Shift+I (or Cmd+Option+I on macOS) to open the Chrome Developer Console. Alternatively, you can also access the Developer Console by going to the Chrome menu (three dots at the top-right corner) > More Tools > Developer Tools.

Reading and Writing Cookie Values

Reviewing the application there are GET and POST calls to a controller methods of faveColourController and faveColourPostController respectively.

The faveColourController method called with a GET call appears as follows:

SNIPPET: src/controllers/controller.ts

This controller retrieves the user's favorite colour from a cookie (or uses a default value), increments a visit count stored in another cookie, sets the updated visit count cookie in the response, determines the colour code based on the favorite colour, and renders the "favecolour" view with the relevant data.

  1. It takes two parameters: req (representing the request object) and res (representing the response object).
  2. It initializes the myFaveColour variable with a default value of "red".
  3. It checks if the cookie named "cookieFaveColour" exists in the request's cookies. If it does, the value of myFaveColour is updated with the value of the cookie.
  4. It initializes the visitCount variable with a default value of 1.
  5. It checks if the cookie named "visitCount" exists in the request's cookies. If it does, the value of visitCount is updated by parsing the cookie's value as an integer and incrementing it by 1.
  6. It sets a new cookie named "visitCount" in the response with the updated value of visitCount. The cookie is set to expire in 900000 milliseconds (15 minutes) and is marked as httpOnly, meaning it cannot be accessed or modified by client-side JavaScript.
  7. It calls the sortColour function to determine the colourCode based on the myFaveColour.
  8. It renders the "favecolour" view using res.render(), passing an object with data to be rendered in the view. The object contains properties such as the title, faveColour, colourCode, and visitCount.
SNIPPET: src/controllers/controller.ts

This controller handles the logic for the POST request. The controller handles the submission of a form with the user's favorite colour selection. It retrieves the selected colour, determines the colour code, sets a cookie to store the selected colour, retrieves the visit count from a cookie, and renders the "favecolour" view with the updated data.

  1. It takes two parameters: req (representing the request object) and res (representing the response object).
  2. It retrieves the value of the faveColour field from the request's body using req.body.faveColour and assigns it to the myFaveColour variable.
  3. It calls the sortColour function to determine the colourCode based on the myFaveColour.
  4. It sets a new cookie named "cookieFaveColour" in the response with the value of myFaveColour. This cookie will store the user's selected favorite colour.
  5. It retrieves the value of the "visitCount" cookie from the request's cookies and assigns it to the visitCount variable.
  6. It renders the "favecolour" view using res.render(), passing an object with data to be rendered in the view. The object contains properties such as the title, faveColour (retrieved from the request's body), colourCode, and visitCount.

Once you pick a colour you should see the cookies in the Chrome Developer console.

Favourite Colour Cookie in Chrome Inspector

By deleteing the cookies from the Chrome Developer console you can see the effect on the display, ie setting the counter back to 1 and/or the colour back to red.

Deleting a Cookie

The /reset route will call the resetController that uses the res.clearCookie to remove th cookies, replicated the deletion of the cookies through the console.

SNIPPET: src/controllers/controller.ts

Persistent Cookies

To demonstrate how the cookies are stored in the browser, open and close the browser window to see the cookie data is retained. Alternatively, open a different browser to see how the cookies have not yet been set (as the cookies are individual to each browser).

Cookies on there own will not provide a secure enough login system, so we next need to look at the concept of sessions.

Next: Sessions