Return and pass on request IDs, and give /v1/e/ ETag, 304 and HEAD (closes #84) #179
@@ -137,6 +137,12 @@ path under `/v1/` answers 200, in maintenance mode too.
|
|||||||
authentication with `metrics.username` and `metrics.password`. Answers: 200;
|
authentication with `metrics.username` and `metrics.password`. Answers: 200;
|
||||||
401 without them; 404 when they are not set, as the route then does not exist.
|
401 without them; 404 when they are not set, as the route then does not exist.
|
||||||
|
|
||||||
|
Every response carries an `X-Request-ID` header holding the request's ID, which
|
||||||
|
a client can quote when reporting a problem: the request's own `X-Request-ID`
|
||||||
|
when it sent one, as a reverse proxy in front of pixa may, otherwise one pixa
|
||||||
|
makes up from its host name, a random string chosen at startup and a counter.
|
||||||
|
pixa's log line for the request carries the same ID as `request_id`.
|
||||||
|
|
||||||
Both `POST` routes accept only a form that pixa's own page served: the page puts
|
Both `POST` routes accept only a form that pixa's own page served: the page puts
|
||||||
a token in the form and sets a cookie to match, and a request without both is
|
a token in the form and sets a cookie to match, and a request without both is
|
||||||
refused with 403, so another site cannot submit the form from a visitor's
|
refused with 403, so another site cannot submit the form from a visitor's
|
||||||
|
|||||||
@@ -115,6 +115,20 @@ func (s *Middleware) RateLimit(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RequestIDResponseHeader returns a middleware that sends the request's ID as
|
||||||
|
// the X-Request-Id response header, so a client can quote it when reporting a
|
||||||
|
// problem. The ID is the one chi's RequestID middleware stored in the request
|
||||||
|
// context, so RequestID must run first.
|
||||||
|
func (s *Middleware) RequestIDResponseHeader() 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(middleware.RequestIDHeader,
|
||||||
|
middleware.GetReqID(r.Context()))
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type loggingResponseWriter struct {
|
type loggingResponseWriter struct {
|
||||||
http.ResponseWriter
|
http.ResponseWriter
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ func (s *Server) SetupRoutes() {
|
|||||||
|
|
||||||
s.router.Use(middleware.Recoverer)
|
s.router.Use(middleware.Recoverer)
|
||||||
s.router.Use(middleware.RequestID)
|
s.router.Use(middleware.RequestID)
|
||||||
|
s.router.Use(s.mw.RequestIDResponseHeader())
|
||||||
s.router.Use(s.mw.ClientIP())
|
s.router.Use(s.mw.ClientIP())
|
||||||
s.router.Use(s.mw.SecurityHeaders())
|
s.router.Use(s.mw.SecurityHeaders())
|
||||||
s.router.Use(s.mw.Logging())
|
s.router.Use(s.mw.Logging())
|
||||||
|
|||||||
Reference in New Issue
Block a user