I wrote an indepth blog post about understanding how HTTP works in GO and in that post, i introduced the concept of middleware with the hope of writing about them in the future. Well, welcome to the future.
What is a middleware ?
Middleware is computer software that provides services to software applications beyond those available from the operating system. – Wikipedia
While that is specific to an operating system, this concept has being applied in HTTP and it has been proven to work pretty much well.
In a web app, Middleware is a piece of code that sits between a
HTTP request and a
Middleware can be run after a response.
For the most parts, we need to run some common operations on a set of routes. Say for instance, we have a
- We obviously don’t want a non-logged in user to access that route.
- We don’t want Peter to be able to visit sensitive routes like
Middleware can also work for stuffs like logging the current request (request ID ?) or adding
X-Retry-After HTTP headers to a response. Technically anything.
When Middleware is added to a web application, HTTP flow looks like this =>
- Middleware handler
- App handler (say
- Middleware handler (not necessary, can skip this)
A primer to this section would be understanding how HTTP works in Golang.. Here is one to level up
A middleware is nothing more than a regular
HTTP handler that filters out requests and dispatch them (HTTP requests) to children handlers.
I called them Children handlers since they usually come in form of a chain..
PostUseris the handler that actually registers a user into the application.
Let’s have a look at a very basic example of a Middleware.
Say we are building an API, we have to return the correct HTTP headers. We can build a middleware that makes sure all our routes return an HTTP content type of
While this is a silly example,
json is actually a middleware. It applies the correct content type to responses.
A real world example
Let’s build a middleware that would protect a route from users without a valid api token.
This would be very simple, the user just needs to pass in the token via the
Authorization: Bearer xxx Headers, then we parse out the value, check if it is a valid token.
If it is, we authenticate the user to view his profile. Requests with an invalid Bearer token would error out.
jsonHandler is from the previous example. It just happened to be renamed. The app handler for the profile route is
profileHandler, we don’t have that yet. So we write it.
The flow is
- HTTP Mux
- jsonHandler (middleware)
- profile (middleware)
- profileHandler (app handler)
Only users with a valid token should be allowed in
Once a user is logged in, a response containing his/her profile would be sent.
To test this, we need to run
curl -H "Authorization: Bearer abc123" http://localhost:8000/profile -i (our sample user, horus has his token as abc123).
Ok, that works.. Let’s try an invalid token, say (abc12)..
curl -H "Authorization: Bearer abc12" http://localhost:8000/profile -i