Open
Description
🚀 Feature
PR
Problem
The grpc-gateway functionality supports REST ednpoint registration directly to ServeMux without using GRPC-server. Accordingly, interceptors for grpc are not called and HTTP route pattern is set at the moment of service method call. So we have to wrap ServeMux in custom middleware for logging, metrics, authorization and the like. The solution works quite well, but it has 2 significant drawbacks:
- the ability to determine an existing route before the middleware is triggered is lost. That is, the API client can send requests via non-existent routes and these requests will be logged, authorized and generally perform any logic when there is no need to do so.
// register POST /hello-world
err := helloworld.RegisterHelloWorldServiceHandlerServer(context.Background(), serveMux, service)
if err != nil {
panic(err)
}
- In middleware there is no possibility to get http pattern of the route before the request is executed. Pattern is placed in context.Context only after execution of the generated service method code. In fact, we get access to the route only after the request is processed.
func CustomMiddleware() func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
pattern, ok := runtime.HTTPPathPattern(r.Context()) // path pattern NOT exist in context
next.ServeHTTP(w, r)
pattern, ok := runtime.HTTPPathPattern(r.Context()) // path pattern exist in context
})
}
}
Solution
- Add
Middleware(HandlerFunc) HundlerFunc
type to the runtime package - Add a middlewares slice to the ServeMux structure and when adding a new route, apply middlewares to the route handler.
- The struct pattern implements the String method and prints the path of the route, so it would be logical to put this object in context.Context to access it from middleware
Metadata
Assignees
Labels
No labels