Skip to content

Feat: add http handler middleware #4319

Open
@nikitaksv

Description

🚀 Feature

PR

#4290

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:

  1. 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)
}
  1. 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

  1. Add Middleware(HandlerFunc) HundlerFunc type to the runtime package
  2. Add a middlewares slice to the ServeMux structure and when adding a new route, apply middlewares to the route handler.
  3. 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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions