HTTP middleware
- Go course
- Advanced
- Lesson 32/68
- 4 min
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
package main
import (
"fmt"
"net/http"
"net/http/httptest"
)
func main() {
// buraya yaz
}Sample solution
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
return http.____(func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r)
})
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 |