CodeBlanks Logo Icon CodeBlanks

Middleware chain

Learn to chain multiple middlewares.

Middleware chain

Middleware is wrapped inside each other to form a chain. The outermost runs first:

h := logla(yetki(api))  // request: logla → yetki → api

With many middleware a readable helper is written:

func zincir(h http.Handler, mw ...func(http.Handler) http.Handler) http.Handler {
    for i := len(mw) - 1; i >= 0; i-- {
        h = mw[i](h)
    }
    return h
}

h := zincir(api, logla, yetki)  // logla still first

Why order matters

Recover middleware must be outermost so it catches every panic inside. If logging sits near the outside it records unauthorized requests too; inside the auth check it records only those that pass. The order is a design decision: zincir(api, recover, logla, yetki) is a common arrangement.

Practice Build a chain

Write harf(s string) func(http.Handler) http.Handler, which builds middleware that prints a letter. Send a request through h := harf("A")(harf("B")(son)); the son handler prints C.

Starter code

main.go
package main

import (
    "fmt"
    "net/http"
    "net/http/httptest"
)

func main() {
    // buraya yaz
}

Sample solution

main.go
package main

import (
    "fmt"
    "net/http"
    "net/http/httptest"
)

func harf(s string) func(http.Handler) http.Handler {
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            fmt.Println(s)
            next.ServeHTTP(w, r)
        })
    }
}

func main() {
    son := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Println("C") })
    h := harf("A")(harf("B")(son))
    h.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest("GET", "/", nil))
}

Expected output

A
B
C

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 In the chain <code>a(b(c(h)))</code>, which runs first on the way in?

  • b
  • a Correct answer
  • c
  • h

Explanation: The outermost wrapper receives the request first; on the way out the order reverses.

2 Wrap from the end

Question
for i := len(mw) - 1; i >= 0; i-- {
    h = mw[____](h)
}
Answer
for i := len(mw) - 1; i >= 0; i-- {
    h = mw[i](h)
}

Explanation: Wrapping the list from the end keeps the first-listed middleware outermost.

3 Position in the chain

Term Meaning
Recover Outermost
Log Near the outside
Auth Near the handler
api Innermost

All lessons in Advanced