Apply Middleware to Your Route Handlers

· 304 words · 2 minutes read

Middleware is a term used in many different ways within software development, but we’re referring to it as a way to wrap requests and responses in simple abstracted functions which can be applied to some routes easily.

In our example below we’re using an AuthMiddleware to check incoming requests for the correct api key and rejecting them if they don’t. Another good example for this technique is applying headers to responses, if you know the content type of the response, we can set it in middleware.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package main

import (
    "io"
    "net/http"
)

const (
    MyAPIKey = "MY_EXAMPLE_KEY"
)

func main() {

    // Create an example endpoint/route
    http.Handle("/", Middleware(
        http.HandlerFunc(ExampleHandler),
        AuthMiddleware,
    ))

    // Run...
    if err := http.ListenAndServe(":8080", nil); err != nil {
        panic(err)
    }
}

// Middleware (this function) makes adding more than one layer of middleware easy
// by specifying them as a list. It will run the last specified handler first.
func Middleware(h http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
    for _, mw := range middleware {
        h = mw(h)
    }
    return h
}

// AuthMiddleware is an example of a middleware layer. It handles the request authorization
// by checking for a key in the url.
func AuthMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

        requestKey := r.URL.Query().Get("key")
        if len(requestKey) == 0 || requestKey != MyAPIKey {
            // Report Unauthorized
            w.Header().Add("Content-Type", "application/json")
            w.WriteHeader(http.StatusUnauthorized)
            io.WriteString(w, `{"error":"invalid_key"}`)
            return
        }

        next.ServeHTTP(w, r)
    })
}

func ExampleHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Add("Content-Type", "application/json")
    io.WriteString(w, `{"status":"ok"}`)
}

Example:

Image of Author Edd Turtle

Author:  Edd Turtle

Edd is the Lead Developer at Hoowla, a prop-tech startup, where he spends much of his time working on production-ready Go and PHP code. He loves coding, but also enjoys cycling and camping in his spare time.

See something which isn't right? You can contribute to this page on GitHub or just let us know in the comments below - Thanks for reading!