mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
32354261d3
Extracts part of the prometheus middleware that stores the route information in the request context into its own middleware. Also adds request method information to context. Relates to https://github.com/coder/internal/issues/1214
72 lines
1.7 KiB
Go
72 lines
1.7 KiB
Go
package httpmw
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
type (
|
|
httpRouteInfoKey struct{}
|
|
)
|
|
|
|
type httpRouteInfo struct {
|
|
Route string
|
|
Method string
|
|
}
|
|
|
|
// ExtractHTTPRoute retrieves just the HTTP route pattern from context.
|
|
// Returns empty string if not set.
|
|
func ExtractHTTPRoute(ctx context.Context) string {
|
|
ri, _ := ctx.Value(httpRouteInfoKey{}).(httpRouteInfo)
|
|
return ri.Route
|
|
}
|
|
|
|
// ExtractHTTPMethod retrieves just the HTTP method from context.
|
|
// Returns empty string if not set.
|
|
func ExtractHTTPMethod(ctx context.Context) string {
|
|
ri, _ := ctx.Value(httpRouteInfoKey{}).(httpRouteInfo)
|
|
return ri.Method
|
|
}
|
|
|
|
// HTTPRoute is middleware that stores the HTTP route pattern and method in
|
|
// context for use by downstream handlers and services (e.g. prometheus).
|
|
func HTTPRoute(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
route := getRoutePattern(r)
|
|
ctx := context.WithValue(r.Context(), httpRouteInfoKey{}, httpRouteInfo{
|
|
Route: route,
|
|
Method: r.Method,
|
|
})
|
|
next.ServeHTTP(w, r.WithContext(ctx))
|
|
})
|
|
}
|
|
|
|
func getRoutePattern(r *http.Request) string {
|
|
rctx := chi.RouteContext(r.Context())
|
|
if rctx == nil {
|
|
return ""
|
|
}
|
|
|
|
routePath := r.URL.Path
|
|
if r.URL.RawPath != "" {
|
|
routePath = r.URL.RawPath
|
|
}
|
|
|
|
tctx := chi.NewRouteContext()
|
|
routes := rctx.Routes
|
|
if routes != nil && !routes.Match(tctx, r.Method, routePath) {
|
|
// No matching pattern. /api/* requests will be matched as "UNKNOWN"
|
|
// All other ones will be matched as "STATIC".
|
|
if strings.HasPrefix(routePath, "/api/") {
|
|
return "UNKNOWN"
|
|
}
|
|
return "STATIC"
|
|
}
|
|
|
|
// tctx has the updated pattern, since Match mutates it
|
|
return tctx.RoutePattern()
|
|
}
|