Skip to content

Instantly share code, notes, and snippets.

@paxan
Last active April 26, 2023 00:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paxan/5b8ecb8e51f633c712d161f911b6e211 to your computer and use it in GitHub Desktop.
Save paxan/5b8ecb8e51f633c712d161f911b6e211 to your computer and use it in GitHub Desktop.
HTTP middlewares in Go from the first principles
package main
import (
"context"
"fmt"
"log"
"net/http"
"sync/atomic"
)
// hello is your HTTP web application.
func hello() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello world (rid: %q)\n", RID(r.Context()))
})
}
// addRID is a middleware that grabs the request ID value from the specified
// header, and puts into the request context passed to the upstream handler.
func addRID(ridHeader string, handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
handler.ServeHTTP(
w,
r.WithContext(context.WithValue(
r.Context(),
ridKey,
r.Header.Get(ridHeader))))
})
}
// RID returns the request ID from the context.
func RID(ctx context.Context) string {
rid, _ := ctx.Value(ridKey).(string)
return rid
}
var ridKey = &struct{ name string }{"request id"}
// requestCounter is a middleware that counts requests.
func requestCounter(handler http.Handler) http.Handler {
var count uint64
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("request count: %v", atomic.AddUint64(&count, 1))
handler.ServeHTTP(w, r)
})
}
func main() {
http.ListenAndServe(
"localhost:8888",
requestCounter(
addRID("X-RID",
hello())))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment