Documentation ¶
Overview ¶
Package middleware contains common used HTTP-server middlewares:
- RequireRequestId
- RequestLogger
- Recoverer
... and DefaultChain func to add those middlewares to http-handler.
All middlewares are compatible with std http.Handler
Index ¶
- Variables
- func Chain(h http.Handler, middlewares ...func(next http.Handler) http.Handler) http.Handler
- func DefaultChain(h http.Handler, log *app.Logger) http.Handler
- func Recoverer(log *app.Logger) func(next http.Handler) http.Handler
- func RequestLogger(log *app.Logger) func(next http.Handler) http.Handler
- func RequireRequestId(next http.Handler) http.Handler
Examples ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var ConnectionHeader = textproto.CanonicalMIMEHeaderKey("connection")
View Source
var (
XRequestIDHeader = textproto.CanonicalMIMEHeaderKey("x-request-id")
)
Functions ¶
func Chain ¶
Chain wraps the handler with provided middlewares:
h = mw_0(mw_1( ... mw_N-1(mw_N(h)) ... ))
func DefaultChain ¶
DefaultChain adds the following middlewares to the handler:
- RequireRequestId
- RequestLogger(log)
- Recoverer(WithLogger(log))
Example ¶
log := app.NewLogger(stdout{}, app.WithLogLevel(slog.LevelInfo)) h := middleware.DefaultChain(http.HandlerFunc(okHandler), log) rr := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodGet, "/", nil) req.Header.Set(middleware.XRequestIDHeader, "XXX-YYY") h.ServeHTTP(rr, req) fmt.Println("response:", rr.Body.String())
Output: {"time":"2006-01-02T15:05:06.000000000+07:00","level":"INFO","msg":"request completed","component":"middleware/RequestLogger","method":"GET","path":"/","remote_addr":"","user_agent":"","resp_code":200,"bytes":12,"resp_time":"1ms","request_id":"XXX-YYY"} response: XXX-YYY - OK
func Recoverer ¶
Recoverer catches handler panic, log it and send http.StatusInternalServerError to client
Example ¶
log := app.NewLogger(stdout{}, app.WithLogLevel(slog.LevelInfo)) recoverer := middleware.Recoverer(log) h := recoverer(http.HandlerFunc(panicHandler)) rr := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodGet, "/", nil) h.ServeHTTP(rr, req)
Output: {"time":"2006-01-02T15:05:06.000000000+07:00","level":"ERROR","msg":"fatal error","component":"middleware/Recoverer","error":"FATAL!!!","stacktrace":"..."}
func RequestLogger ¶
RequestLogger logs requests using provided logger
Checks response code:
- if 0 < code < http.StatusBadRequest logs INFO
- otherwise logs ERROR
Example (Bad) ¶
log := app.NewLogger(stdout{}, app.WithLogLevel(slog.LevelInfo)) rl := middleware.RequestLogger(log) h := rl(http.HandlerFunc(badHandler)) rr := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodGet, "/", nil) h.ServeHTTP(rr, req)
Output: {"time":"2006-01-02T15:05:06.000000000+07:00","level":"ERROR","msg":"request failed","component":"middleware/RequestLogger","method":"GET","path":"/","remote_addr":"","user_agent":"","resp_code":400,"bytes":7,"resp_time":"1ms"}
Example (Ok) ¶
log := app.NewLogger(stdout{}, app.WithLogLevel(slog.LevelInfo)) rl := middleware.RequestLogger(log) h := rl(http.HandlerFunc(okHandler)) rr := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodGet, "/", nil) h.ServeHTTP(rr, req)
Output: {"time":"2006-01-02T15:05:06.000000000+07:00","level":"INFO","msg":"request completed","component":"middleware/RequestLogger","method":"GET","path":"/","remote_addr":"","user_agent":"","resp_code":200,"bytes":5,"resp_time":"1ms"}
func RequireRequestId ¶
RequireRequestId checks if XRequestIDHeader exists.
If ok, adds request id into context. If not, sends error response with ErrCodeValidation
Example (Bad) ¶
h := middleware.RequireRequestId(http.HandlerFunc(okHandler)) rr := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodGet, "/", nil) h.ServeHTTP(rr, req) fmt.Println("response:", rr.Code, rr.Body.String())
Output: response: 400 {"error":"ERR_VALIDATION","message":"X-Request-Id header is required"}
Example (Ok) ¶
h := middleware.RequireRequestId(http.HandlerFunc(okHandler)) rr := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodGet, "/", nil) req.Header.Set(middleware.XRequestIDHeader, "XXX-YYY") h.ServeHTTP(rr, req) fmt.Println("response:", rr.Code, rr.Body.String())
Output: response: 200 XXX-YYY - OK
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.