Skip to content

Instantly share code, notes, and snippets.

@jaredhirsch
Last active March 19, 2021 08:54
Show Gist options
  • Save jaredhirsch/4963424 to your computer and use it in GitHub Desktop.
Save jaredhirsch/4963424 to your computer and use it in GitHub Desktop.
ETags & If-None-Match headers: a dialogue

ETags & If-None-Match headers: a dialogue

1st request.

browser: can haz foo?

GET /foo HTTP/1.1

1st response.

server: o hai, dis version 12345.

note, there's always an empty line between headers & body.

HTTP/1.1 200 OK
ETag: "12345"

<!doctype html><p>foo.

2nd request.

browser: hai. can haz latest? i haz 12345.

GET /foo HTTP/1.1
If-None-Match: "12345"

2nd response if current version is unchanged

server: u haz latest lol!

HTTP/1.1 304 Not Modified

2nd response if current version has changed

if page has changed + new version is 56789,

server: lol wut! herez latest

HTTP/1.1 200 OK
ETag: "56789"

<!doctype html><p>new foo.

Because the 304 has no response body, client and server save bytes & time.

GET requests with If-None-Match headers are called conditional GET requests, since the server only returns a response body if there's new content. You can also use date-based validation to issue conditional GETs, saving transfer bandwidth without implementing ETags. The flow is the same, except the server sends down an Expires date, and the browser sends it back as a Last-Modified header.

See the HTTP 1.1 RFC for more details. It's more readable than you'd think.

Also, those are valid html5 documents in the examples; I just omitted optional tags.

@llimacruz
Copy link

In my tests using If-None-Match header, ExpressJS is returning 304 but all 'get' code is being executed.
How can I on the server intercept the request and avoid unnecessary processing?
Thanks!

@JeffLuckett
Copy link

JeffLuckett commented May 31, 2018

@llimacruz - It's up to your code to do pre-work to determine if changes were made. How you do this will be up to your own application's implementation, but you're going to need to assemble the data that was used to create the etag in the prior response to determine if it matches.

At minimum, etags allow you to save the time of sending a (potentially large) response back to the server, even if you still have to do the same amount of "work" on the server requesting resources, etc... This can be very fast if you're using effectively server-side caching though, since you'll just be hitting your caching layer instead of going to your database.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment