Bisexual Pride

Last week, we learned that cross-origin resource sharing (CORS) is a mechanism based on HTTP headers. But what exactly are HTTP headers?

HTTP headers

Here’s the definition of HTTP headers from the MDN Web Docs:

HTTP headers let the client and the server pass additional information with an HTTP request or response. An HTTP header consists of its case-insensitive name followed by a colon (:), then by its value. Whitespace before the value is ignored.

Inspecting HTTP headers

You can inspect HTTP headers using the Network panel in your browser’s developer tools, such as the Network Monitor in Firefox DevTools and the Network panel in Chrome DevTools. Once you’ve chosen a request from the network request list, you’ll see the network request details pane. This is where you’ll find the HTTP headers for the request.

A screenshot of the network request details pane in Firefox 106. The Headers tab is selected and some of the response headers are visible.
The network request details pane in Firefox 106.

Request headers

I just entered the URL for this very website into my browser’s address bar. The following are some of the request headers which my browser sent to the server where my website is hosted.

{
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Host": "barker.codes",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0"
}

Accept

The Accept header indicates what content types my browser will accept. My browser is saying that it prefers:

  1. HTML/XHTML documents and AVIF/WebP images
  2. XML documents
  3. Any other content type

Notice that the text/html, application/xhtml+xml, image/avif, and image/webp content types don’t have a ;q= suffix. This means these content types have the default quality value of 1.0. Meanwhile, the application/xml content type has a quality value of 0.9 and the */* content type has a quality value of 0.8.

Accept-Encoding

The Accept-Encoding header indicates what content encoding my browser will accept. This is usually a compression algorithm. My browser is saying that it will accept the gzip, deflate, and br compression formats. Because none of them specifies a quality value, they’re all equally weighted at 1.0.

Host

The Host header indicates the host (and port number) of the server where the request is being sent. My browser is saying it has sent the request to the host barker.codes. Because the port number isn’t specified, it will use the default port of 443 for HTTPS and 80 for HTTP. For example, try to visit https://barker.codes:443 and it should still work!

Sec-Fetch-*

The Sec-Fetch-* headers provide additional information about the request context. My browser is saying that I initiated the request myself by entering the URL into my browser’s address bar. This is in contrast to a CORS request, for example, where the user doen’t make the request directly. See Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site, and Sec-Fetch-User.

User-Agent

The User-Agent header contains details about the user agent, such as the user’s browser and operating system. My browser is saying that I’m using Firefox on macOS.

Response headers

The following are some of the response headers which the server where my website is hosted sent back to my browser.

{
"Cache-Control": "public, max-age=0, must-revalidate",
"Content-Encoding": "br",
"Content-Length": 2890,
"Content-Type": "text/html; charset=UTF-8",
"ETag": "\"3590a6cc982a55b4cd3e99df1378b6f4-ssl-df\"",
"Strict-Transport-Security": "max-age=31536000",
"Vary": "Accept-Encoding"
}

Cache-Control

The Cache-Control header controls caching in browsers and in shared caches such as content delivery networks (CDNs). Using the public directive, the max-age directive and the must-revalidate directive, the server is essentially saying that the response can’t be cached.

Content-Encoding

The Content-Encoding header lists the content encodings that have been applied to the response body. The server is saying that the response was encoded using the Brotli compression algorithm. Remember the Accept-Encoding request header? My browser said it would accept the Brotli algorithm!

Content-Length

The Content-Length header indicates the size of the response body in bytes. The server is saying that the size of the response body was 2890 bytes after it was compressed using the Brotli compression algorithm.

Content-Type

The Content-Type header indicates the content type of the response body before compression. The server is saying that this is an HTML response with UTF-8 character encoding. Remember the Accept request header? My browser said it would accept (and actually prefer) HTML!

ETag

The ETag header is an identifier for a specific version of a resource. It lets caches be more efficient and save bandwidth, as a web server does not need to resend a full response if the content was not changed. The value above is likely a hash of the content, a hash of the last modification timestamp, or just a revision number (MDN).

Strict-Transport-Security

The Strict-Transport-Security header means that the site should only be accessed using HTTPS and that HTTP requests should be converted to HTTPS requests. Using the max-age=31536000 directive, the server is saying that the browser should remember this for 31,536,000 seconds (~1 year).

Vary

The Vary header lists the request headers that could have influenced the creation of the response. The server is saying that the response could change based on the value of the Accept-Encoding header. This is because the server will try to use an encoding that the browser said it will accept. This is called content negotiation.

Summary

There are many more HTTP headers not covered in this article. I encourage you to read about them in the MDN Web Docs. What I’d like you to take away from this article is that HTTP headers aren’t “magic invisible things”. They’re just a handful of key-value pairs which are sent and received with each request and response.