Skip to content

runtime.ServeMux: wrong handler chosen #5771

@movsb

Description

@movsb

🐛 Bug Report

Adding custom routes to the mux | gRPC-Gateway

The gRPC-Gateway allows you to add custom routes to the serve mux, for example, if you want to support a use case that isn’t supported by the gRPC-Gateway, like file uploads.

So, I have a ListFiles method in gRPC service proto which list files: /v3/files.
And I registered another GetFile method manually using HandlePath: /v3/files/{path=**}.

The final routing tree may be like the following:

func main() {
	mux := runtime.NewServeMux()
	mux.HandlePath(`GET`, `/v3/files`, func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) {
		fmt.Fprintln(w, 1, pathParams)
	})
	mux.HandlePath(`GET`, `/v3/files/{path=**}`, func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) {
		fmt.Fprintln(w, 2, pathParams)
	})
	http.ListenAndServe(`:8080`, mux)
}

Result:

$ curl localhost:8080/v3/files
2 map[path:]
$ curl localhost:8080/v3/files/a.txt
2 map[path:a.txt]

I'm expecting that the first request is routing the first handler, which prints 1.

Swapping the handling order fixes this problem, but I just think that the handling order shouldn't matter:

  1. s.handlers[meth] = append([]handler{{pat: pat, h: h}}, s.handlers[meth]...)
  2. for _, h := range s.handlers[r.Method] {

The handlers added later will be put into the front of the handlers slice, and will be used firstly.

Metadata

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