DEV Community

Oleks
Oleks

Posted on

Go middleware example. How to alter a HTTP handler result?

Let's imagine a situation when you want to alter a result, returned by some http handler to the client. Fortunately, Golang provides an easy mechanism for that, called a middleware.

I will dive directly into the source code, to save your time.

Imagine, we have this simple webserver (here I'm using a chi router):

package main import ( "bytes""github.com/go-chi/chi""io""log""net/http" ) func main() { r := chi.NewRouter() r.Get("/", myFirstHandler) http.ListenAndServe(":3000", r) } func myFirstHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("This is a main page")) } 
Enter fullscreen mode Exit fullscreen mode

When we run this application and visit a frontpage htttp://localhost:3000/, you can see this:
golang golang

And now we got a new requirement to create another handler which should get all response data from myFirstHandler and add some modification on top.

We can do it easily in this way:

// Adds a new router handler with a middleware myMiddleware.  r.With(myMiddleware).Get("/other", myFirstHandler) 
Enter fullscreen mode Exit fullscreen mode

To be able to read a response from another handler, we have to implement our own ResponseWriter:

type MyResponseWriter struct { http.ResponseWriter buf *bytes.Buffer } // Here we are implementing a Write() function from ResponseWriter with our custom instructions.  func (myrw *MyResponseWriter) Write(p []byte) (int, error) { return myrw.buf.Write(p) } 
Enter fullscreen mode Exit fullscreen mode

And finally, let's write our middleware:

func myMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Create a response writer: myResponseWriter := &MyResponseWriter{ ResponseWriter: w, buf: &bytes.Buffer{}, } // Here we are pssing our custom response writer to the next http handler. next.ServeHTTP(myResponseWriter, r) // Here we are adding our custom stuff to the response, which we received after http handler execution.  myResponseWriter.buf.WriteString(" and some additional modifications") // And, finally, we are copiing everything back to the original response writer. if _, err := io.Copy(w, myResponseWriter.buf); err != nil { log.Printf("Failed to send out response: %v", err) } }) } 
Enter fullscreen mode Exit fullscreen mode

Now, if we run our server again and go to /other path, we will see this:
golang golang

This was a silly example, which will never happen in real life, but, I hope you got an overview of how you can play with HTTP handlers and middlewares.

The source code you can find in this repository: https://github.com/alexsergivan/blog-examples/tree/master/middleware

Top comments (1)

Collapse
 
rdasilva_fispan profile image
rdasilva-fispan

Is there any way I can read what the enclosing handler is sending? I would like to check inspect the response body and the HTTP status code of the enclosing handler on my enclosed handler and take action based on what I am receiving there?

Thank you!