Course outline · 0% complete

0/25 lessons0%

Course overview →

Cookies: HTTP has no memory

lesson 6-1 · ~10 min · 18/25

Unit 4 covered where extra information such as Content-Type travels in an HTTP message.

In headers, the Name: value lines before the blank line.

Headers carry metadata in both directions, as lessons 4-1 and 4-2 showed. This unit is about the two headers that give the stateless web a memory: Set-Cookie coming down, and Cookie going back up.

Every request is a stranger

HTTP is stateless: the server handles each request on its own and remembers nothing afterwards. Request #2 does not know request #1 happened. So how does a site keep you logged in across hundreds of requests?

Cookies. A cookie is a small piece of text the server asks the browser to remember, using the Set-Cookie response header:

HTTP/1.1 200 OK
Set-Cookie: session=abc123; Path=/; HttpOnly; Max-Age=3600

The part before the first ; is the actual cookie: a name (session) and a value (abc123). Everything after are attributes, instructions about how to handle it:

  • Path=/: send it with requests to every path on this site
  • HttpOnly: page JavaScript cannot read it (protects it from scripts)
  • Max-Age=3600: forget it after 3600 seconds

From then on, the browser automatically attaches the cookie to every request to that site, in the Cookie request header:

GET /inbox HTTP/1.1
Host: example.com
Cookie: session=abc123
BrowserServerPOST /loginSet-Cookie: session=abc123GET /inbox + Cookie: session=abc123GET /settings + Cookie: session=abc123one Set-Cookie down, a Cookie header on every request after it
Set-Cookie comes down once, and the browser echoes Cookie back up on every later request without being asked again.

Parsing a Set-Cookie header

The same trimming patterns from lesson 1-2: cut off the header name, keep what is before the first semicolon, then split on =.

header="Set-Cookie: session=abc123; Path=/; HttpOnly; Max-Age=3600"

raw=${header#Set-Cookie: }
cookie=${raw%%;*}
name=${cookie%%=*}
value=${cookie#*=}

echo "name: $name"
echo "value: $value"

Output

name: session
value: abc123

Four trims, each removing one layer. The header name goes first, then the attributes, then the name and value separate from each other.

Note that ${cookie#*=} uses the single # for the shortest match, which is deliberate. A cookie value containing an = would survive intact, whereas the doubled form would have cut at the last one and lost part of the value.

That is a real concern rather than a hypothetical, since session tokens are often base64 text, and base64 padding is made of = characters.

Listing the attributes

Strip everything through the first ; , then turn the remaining semicolons into newlines.

header="Set-Cookie: session=abc123; Path=/; HttpOnly; Max-Age=3600"

attrs=${header#*; }
echo "$attrs" | tr ';' '\n' | while read -r attr; do
  echo "attribute: $attr"
done

Output

attribute: Path=/
attribute: HttpOnly
attribute: Max-Age=3600

Reading the pipeline

  • ${header#*; } removes everything up to and including the first ; , leaving Path=/; HttpOnly; Max-Age=3600.
  • tr ';' '\n' replaces each remaining semicolon with a newline, which turns one line into three so the loop can read them.
  • read -r strips the leading spaces for you, so each $attr comes out clean without extra trimming.
  • Notice HttpOnly has no value at all. Cookie attributes are a mix of Name=value pairs and bare flags, so any real parser has to handle both shapes.

How the value gets back

The browser automatically adds a Cookie: session=abc123 request header.

That automatic echo is the whole mechanism. The server sets the cookie once, and the browser attaches it to every later request to that site without any code or any user action.

The site can then recognize request 500 as the same visitor as request 1, which is how a stateless protocol supports something as stateful as being logged in.

The automation is also the reason cookies need attributes. Since the browser sends them without being asked, Path, Max-Age, and HttpOnly exist to limit where they go, how long they last, and who can read them.