CodeBlanks Logo Icon CodeBlanks

HTTP middleware

Learn the func(http.Handler) http.Handler pattern.

Wrapping with http.HandlerFunc

http.HandlerFunc is the type that turns a plain function into an http.Handler. Inside middleware it is used to build the new handler as a closure:

func zamanla(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        bas := time.Now()
        next.ServeHTTP(w, r)
        log.Println(r.URL.Path, time.Since(bas))
    })
}

Code before next.ServeHTTP runs on the way in, code after it on the way out.

Middleware with parameters

Middleware that takes settings is written as a function that returns middleware:

func header(ad, deger string) func(http.Handler) http.Handler {
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            w.Header().Set(ad, deger)
            next.ServeHTTP(w, r)
        })
    }
}

h := header("X-Surum", "2")(api)

Practice Before and after

Write izle(next http.Handler) http.Handler: fmt.Println("önce"), next.ServeHTTP, then fmt.Println("sonra"). The handler prints fmt.Println("işleyici"); send one request with httptest.

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 izle(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("önce")
        next.ServeHTTP(w, r)
        fmt.Println("sonra")
    })
}

func main() {
    h := izle(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("işleyici")
    }))
    h.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest("GET", "/", nil))
}

Expected output

önce
işleyici
sonra

Questions and answers

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

1 What happens if middleware doesn't call <code>next.ServeHTTP</code>?

  • The server crashes
  • The request is handled twice
  • The real handler doesn't run; the request ends in the middleware Correct answer
  • Go calls it automatically

Explanation: Continuing the chain is the middleware's job; not calling next stops the request (done on purpose for unauthorized requests).

2 Turn the function into a handler

Question
return http.____(func(w http.ResponseWriter, r *http.Request) {
    next.ServeHTTP(w, r)
})
Answer
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    next.ServeHTTP(w, r)
})

Explanation: http.HandlerFunc converts a function with the right signature into a type that satisfies the Handler interface.

3 Run order

Term Meaning
Before next On the way in
next.ServeHTTP The real handler
After next On the way out
return (no next) Stops the request

All lessons in Advanced