gorilla / mux

Package gorilla/mux is a powerful HTTP router and URL matcher for building Go web servers with 🦍
https://gorilla.github.io
BSD 3-Clause "New" or "Revised" License
20.93k stars 1.85k forks source link

Solution to Issue #751 #773

Open roy-kim-33 opened 1 month ago

roy-kim-33 commented 1 month ago

What type of PR is this? (check all applicable)

Description

Address Issue #751 by using method mismatch flag in Route.Match()

The flag allows Route.Match() to return MethodNotAllowed (405) from an earlier mismatch instead of returning NotFound (404) from a later mismatch (refer to example from #751).

For nested endpoints,

r := mux.NewRouter()
subrouter := r.PathPrefix("/prefix").Subrouter()
subrouter.HandleFunc("/foo", fooHandler).Methods("POST")
subrouter.HandleFunc("/foo", fooIdHandler).Methods("GET").Queries("id", "{id:[0-9]+}")

The following results show some edge cases: PUT /v1/foo?id=1 returns 405 (match second endpoint, desired behavior) GET /v1/foo?id=abc returns 404 (match second endpoint, 400 on second endpoint preferred) POST /v1/foo?id=abc returns 200 (match first endpoint, 405 on second endpoint might be preferred) POST /v1/foo?id=1 returns 200 (match first endpoint, 405 on second endpoint might be preferred) PUT /v1/foo returns 404 (match second endpoint, 405 on first endpoint preferred) GET /v1/foo returns 404 (match second endpoint, 400 on first or 405 on second preferred)

These edge cases can be partially resolved(?) by declaring endpoints in descending order of specificity.

subrouter.HandleFunc("/foo", fooIdHandler).Methods("GET").Queries("id", "{id:[0-9]+}")
subrouter.HandleFunc("/foo", fooHandler).Methods("POST")

PUT /v1/foo?id=1 returns 405 (match first endpoint, desired behavior) GET /v1/foo?id=abc returns 405 (match second endpoint, 400 on first endpoint preferred) POST /v1/foo?id=abc returns 200 (match second endpoint, 405 on first endpoint might be preferred) POST /v1/foo?id=1 returns 200 (match second endpoint, 405 on first endpoint might be preferred) PUT /v1/foo returns 405 (match second endpoint, desired behavior) GET /v1/foo returns 405 (match second endpoint, 400 on first endpoint might be preferred)

NOTE: might be is a soft suggestion

Related Tickets & Documents

Added/updated tests?

Run verifications and test