Once upon a time, long ago, in a land far, far away, there stood a kingdom. It was a peaceful kingdom and had everything a real kingdom is expected to have: a Grand Council in charge of decisions and proclamations, a noble court consisting of the most well-off and privileged citizenry, and the peasant populace. The council sessions were held within the great inner castle walls and only denizens of the kingdom proper were allowed entry, as well as an opportunity to appeal to the Queen and Council. The wall and Queensguard adamantly kept everyone else out.
Welcome… to Backendia.
No, you did not misclick. Your eyes do not deceive you. This is indeed a Medium article about the lifecycle of requests, not cheap Game of Thrones fan fiction or your next Dungeons and Dragons campaign setting. And no, I am not crazy (officially). The concept of a backend router redirecting requests depending on their headers and content is not dissimilar to a Grand Council filtering, prioritising, handling and responding to requests from the general populace. If you’re somehow still with me for some reason, I will attempt to describe this entire process from the perspective of the kingdom (the backend) as appeals from the public (requests) come in and the appropriate decrees (responses) are issued. Yes, I am a nerd. Allons-y!
Our tale begins one sunny summer morning, on the day of the monthly Appeal-To-The-Queen Day. People from all walks of life are permitted, once a month, to present themselves and their issues, proclamations or suggestions to the Queen and Council, and receive a proper response. But not just anyone may approach the Grand Council — in order to even penetrate the wall of guards surrounding the castle, any potential appealers must first prove their allegiance to the Kingdom proper. There are two ways to do this: for most of the population, merely proving you’re a resident within the Kingdom itself is enough. Thus, providing an official document signed and sealed by the Queen, which states that you reside within the Kingdom or have official business within its borders, is enough to permit you entry into the castle proper and allow you to make your appeal.
The other way to prove your allegiance to the Kingdom is to present a royal decree stating your belonging to the noble court of the kingdom, marking you as a person of blue, noble blood and one of the citizens with full privileges and access rights.
Let’s zoom out from our fantastic tale for a few moments and dissect these two scenarios. If we apply the above to a real-life HTTP request, we can easily establish the similarities in the ways authorization works in our fantasy land and in real life. The first scenario — the peasant proving his allegiance or residence in the Kingdom with an official signed document — can be likened to a real-life request having the proper header discerning it from other potential misguided or intruding requests and establishing it as a request intended for the backend or frontend application in question. These custom headers vary from architecture to architecture, but for token-based authorization systems this is usually an Authorization-static header containing a predefined, agreed-upon string or encrypted value which matches on both the backend and frontend platforms. This header usually does not change during the lifecycle of the application or project and provides a basic level of security and a way of making sure the request points to the right target.
The second scenario — the noble providing his royal decree of belonging — is more akin to an authorised user request with a proper, generated Authorization header. Again, the specifics vary depending on the authorization methods used within the project itself, but for a token-based system such as JWT, this is usually an Authorization header containing the encrypted JWT token of the user or entity accessing the application. The difference between a static authorization and a dynamic one is in the complexity of deriving the content of the header and the degree of individuality that the header grants the request in regards to the application use cases.
A simple example would be an application for news consumption which enables, but does not enforce, registration by the user. Non-registered users can read the news, no problem! Their requests have an Authorization-static header with the proper, pre-defined content, marking them as read-only and allowing access to only the ‘All news’ and ‘Registration’ routes.
However, should the user choose to register, his requests would no longer be identified using solely the static header. Now, his requests would have a proper Authorization header containing (in the case of token-based security systems) a generated, encrypted string which is unique to that user and that user alone. Regardless of authentication method, this header marks his requests as fully empowered and allows him access to all parts of the application, even those which are unavailable to requests with just a static header. In short, he’s a part of the ‘nobility’ for that application.
The inner courtyard starts filling with more and more people as time passes. Soon the Council Chamber doors will open and the guards will start sending people in to see the Council itself to make their appeals. Only people who have successfully proven their residence or allegiance to the Kingdom are permitted into the courtyard, which means that in order to even find yourself here, you have passed the first barrier! Next, the Queensguard redirects you to the proper chamber entry depending on your intents.
A farmer wishes to make a deposit of his best cabbages to the Royal Granary. The courtyard guard signs a sheet of parchment and sends him to a side entrance with a sign above it that reads ‘Royal Granary’. Within the door, another guard reads the parchment and sees that the farmer wishes to deposit cabbages instead of withdrawing from the granary. He leads the farmer into the Small Council chambers dedicated to the Royal Granary and introduces him to the Council members. The farmer states the amount he wishes to deposit and in return, he receives an official sealed document proclaiming his generosity and loyalty to the Crown.
Meanwhile, the royal blacksmith requires more iron for smelting and forging new weapons. As is customary, he submits an official request to the Royal Reserves for the finest iron the kingdom has on offer. After hearing this, the courtyard guard redirects him to the appropriate entryway labeled “Royal Reserves”. The guard inside then reads his signed document and directs him into the council chamber, where he receives his iron and can proceed forging war machines for his Queen and country.
Finally, we have a disturbance at the front gates. A spy from the neighbouring kingdom of Badrequestia attempts to infiltrate the Council Chambers by presenting a falsified document with a fake royal seal “proving” his residence within the kingdom. Although the falsified parchment is almost perfect, the signature on the document doesn’t quite match the Queen’s, and the spy is quickly dealt with. As this was the first attempt from Badrequestia to infiltrate the kingdom, the guards merely turn him away now, but should the attempts continue, the consequences may be more severe. Gotta put that blacksmith’s weapons to use somehow, right?
Back to reality! These last few anecdotes are pretty self-explanatory, but let’s go through them nonetheless. Two of the scenarios describe a request which has a valid Authorization header, while the last one is a bit different in that regard.
The first scenario depicts an authorised request to an endpoint on our API, but the important thing to note is the action the farmer is attempting to perform. He wants to deposit cabbages into an existing resource, the Royal Granary, i.e. perform a PUT action onto an existing entity in the database via the appropriate route. In our story, this works out fine and he receives the appropriate success answer (200 in real life, or a similar Success response).
The second scenario has a blacksmith attempting to access a resource without modifying or adding to the database or API itself. This is a very straightforward depiction of a GET request which serves to access an available resource without modifying it (usually). Again, everything works out fine and our blacksmith walks away satisfied with his 200 response and the resource he needed.
And finally, our Badrequestian spy. This man attempted to pass the authorization checks using a falsified credential (a.k.a. using a mocked header which does not match the required value for either Authorization or Authorization-static we discussed above). As such, the Royal Guard quickly catch on and dump his butt outside the city walls, warning him this time, but also noting that they will be more severe should such a provocation happen again. This is an example of a request gone wrong — for whatever reason, the conditions set by the server were not satisfied fully and the client received an appropriate error response to their request. In this case, the response from the server was something akin to a 401 — Unauthorised error, but it could be anything the server wants. The spy better brace themselves, however! Next time, he might get banned from the kingdom for good! Wonder what the error code on that one would be… leave your ideas in the comments if you have any cute suggestions!
And there you have it. We could, of course, go into way more detail than is actually presented here, but for now, this article is meant to serve as a cutesy way of depicting the lifecycle of some common requests and the responses to them. This is in no way an academic piece of work and should not be regarded as such. That being said, hopefully you walk out of here with a slightly better understanding of server request handling than when you walked in.
Thanks for reading and hope to meet you again really soon in the kingdom of Backendia!
7 qualities we recognise in former athletes and why you should consider them too.