about
projects
blog

HTTP Headers and 304

I started taking Brian Holt's Intro to Realtime course on Front End Masters, because I wanted to get some experience working with web sockets for a project that I have in mind. Lately, I have been also learning Go, and so whenever I am learning something new in Node, I try to translate that learning over to Go as well.


Brian likes to structure his courses by starting from first principles. He usually has the class attempt to recreate the technology from scratch, in order to understand the solution that the technology solves. The project in this course is to build a chat app. We start by exploring various ways in which one could hack together the functionality needed for the app. In this case, we continuously poll the api for updates and display the result on the screen. Then Brian talked about the downsides of the approach, as well as strategies for retries, and back-offs. While transferring the section over to Go with Gin Web Framework, I had to go a little deeper in one particular area.


I noticed that when the GET call to check for updated messages ran in Node, I was getting back a 304 status code, and wondered what a 304 status code was for. 304 is the code for "Not Modified", which means that somehow it was determined that the requested resource had not been updated since the last call to the api, and therefore, the refresh was not necessary. When I implemented everything with the same front end, but with Gin, the status codes were always 200, or 201 if there was a new POST to the chat.


After a little digging, I found that Node "automagically" does some kind of http header magic, while Gin lets the developer handle this themselves. Apparently there are a few HTTP headers that can be used in the client-server handshake to determine how the server will handle the request. When a server responds to a client request, it can send back an ETag, that is an identifier for the state of a resource. When the client makes another request, the client will have an If-None-Match field in the header, that will carry the previous ETag. Then, the server can check to the if the current ETag matches the request If-None-Match. If they do not match, the server process the request and sends back the updated data. If they do match, the server will stop reading at the header, and send back a 304 Not Modified. This ends up being a performance optimization, because the size of the header could be significantly smaller than the entire response.

I ended up writing some custom middleware, that made a hash of my in-memory array on the server using the crypto/md5 go package for the ETag, in order to mimic the functionality I was seeing in Node/Express. ChatGPT recommended sha256, but I remember learning from Jem Young's Full Stack For Front End course, that md5 was faster, and still used for purposes such as this, where maybe you don't need the identifier to be cryptographically unbreakable. It took some time to figure out what was going on, and how to do this, but this is one of the reasons that I like learning different language! I'm excited to move on to the next section of the course, learn more about web sockets, and see how what is different between the Node/Express and Go/Gin back ends.