Go middleware example. How to alter a handler result
2 min read Go Programming

Go middleware example. How to alter a handler result

Let’s imagine a situation when you want to alter the result, returned by some http handler to the client. Fortunately, Golang provides an easy mechanism for that, called a middleware. I’m going to dive directly to the source code, to save your time.

Imagine, we have this simple web server (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"))
}

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

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) 

To be able to read a response from other 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)
}

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)
      }
   })
}

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

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

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

A

Alex

Passionate about web development and sharing knowledge with the community.

Share on X