Go
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)
Exercise 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.
Show example 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))
}
Test yourself
-
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
- Go calls it automatically
Show answer
The real handler doesn't run; the request ends in the middleware — Continuing the chain is the middleware's job; not calling next stops the request (done on purpose for unauthorized requests).
-
Turn the function into a handler
return http.____(func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r)
})
Show answer
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r)
})
-
Run order
- Before next
- On the way in
- next.ServeHTTP
- The real handler
- After next
- On the way out
- return (no next)
- Stops the request
Next lesson: Middleware chain