Checkout https://www.gophersumit.com/series/web-server/ for more.
Middleware is used to provide a processing pipeline for web servers. Middleware is way of providing shared processing functionality for our web handlers. Whenever there is incoming request to our web server, we may want to log it, check if user is authorized etc. While sending response back to client, we may want to perform compressions, set some custom headers etc. These are functionalities that is shared by most handlers or all the handlers. These shared functionalities can be abstracted as middleware.
Middleware operates as chain of calls to
Title: Middleware Processing Pipeline - Flow Client->M1: Client Request M1-->>M1: Authenticate User M1->Client: Unauthorized M1->M2: Next Handler M2-->>M2: Authorize M2-->>M1: Unauthorized M1-->>Client: Unauthorized M2->M3: Next Handler M3-->>M3: Log Request M3->Handler: Next Handler Handler-->>Handler: Processing Handler->M3: Response M3 -->>M3: Log Response M3->M2: Response M2->M1: Response M1->Client: Response
If you recall from first post from this series, we have Handler type defined in
net/http library as:
We have also used
http.DefaultServeMux() to create a new multiplexer for request handling. This multiplexer is
ServeMux type defined as
If you dig further in source code for
net/http, you will find that
ServeMux type implements
building custom middleware
Let's build a simple middleware and plug it in processing pipeline.
For our function to be able to work as valid middleware, it should be pluggable in processing chain. To satisfy this requirement, our function should accept
http.Handler type and it should also return
Things to note about this middleware:
- myFunc is an anonymous function declared in middleware. It closes over
handand will have access to
handsince Go supports Closure.
- We are again using
http.HandlerFuncadaptor function to convert
http.Handlertype which is returned.
- Inside of our anonymous function before call to
hand.ServeHTTP(), we add our middleware logic.
Lets spin a simple web server to set some custom header in every incoming http request.
- For our middleware to be utilized, we can use
Serverstruct as below.
customMiddlewarewill receive the request, it will perform our custom middleware logic and send the request to default server mux that we are creating.
- In our custom middleware, we are setting request header using :
Complete working middleware code :