Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: add http handler middleware #4319

Open
nikitaksv opened this issue May 12, 2024 · 1 comment
Open

Feat: add http handler middleware #4319

nikitaksv opened this issue May 12, 2024 · 1 comment

Comments

@nikitaksv
Copy link
Contributor

nikitaksv commented May 12, 2024

馃殌 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
@johanbrandhorst
Copy link
Collaborator

Thanks for the issue! I'm sympathetic to this, but I'm worried that it will cause confusion to users who are not using the direct-to-implementation pattern. It's cool that this makes it easier to use the direct-to-implementation functionality, but we have to be careful in the implementation of the new API and options to avoid confusing users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants