Skip to content

Commit 395ad81

Browse files
soheilrtcoreydaley
andauthoredAug 17, 2023
[BUG] Inconsistent HTTP status code on query mismatch (#712)
The logical behavior of a router should return an HTTP status code of 404 when a request fails to satisfy route validation logic. Previously, MUX was returning a 405 HTTP status code in some rare scenarios, which was not valid in its case. For more info, See: #704 Fixes #704 **Summary of Changes** 1. Clear the mismatch error of the previous validations on method match. 2. Added related tests > PS: Make sure your PR includes/updates tests! If you need help with this part, just ask! Co-authored-by: Corey Daley <[email protected]>
1 parent 24c3e7f commit 395ad81

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed
 

‎mux_test.go

+47
Original file line numberDiff line numberDiff line change
@@ -2069,6 +2069,53 @@ func TestNoMatchMethodErrorHandler(t *testing.T) {
20692069
}
20702070
}
20712071

2072+
func TestMultipleDefinitionOfSamePathWithDifferentMethods(t *testing.T) {
2073+
emptyHandler := func(w http.ResponseWriter, r *http.Request) {}
2074+
2075+
r := NewRouter()
2076+
r.HandleFunc("/api", emptyHandler).Methods("POST")
2077+
r.HandleFunc("/api", emptyHandler).Queries("time", "{time:[0-9]+}").Methods("GET")
2078+
2079+
t.Run("Post Method should be matched properly", func(t *testing.T) {
2080+
req, _ := http.NewRequest("POST", "http://localhost/api", nil)
2081+
match := new(RouteMatch)
2082+
matched := r.Match(req, match)
2083+
if !matched {
2084+
t.Error("Should have matched route for methods")
2085+
}
2086+
if match.MatchErr != nil {
2087+
t.Error("Should not have any matching error. Found:", match.MatchErr)
2088+
}
2089+
})
2090+
2091+
t.Run("Get Method with invalid query value should not match", func(t *testing.T) {
2092+
req, _ := http.NewRequest("GET", "http://localhost/api?time=-4", nil)
2093+
match := new(RouteMatch)
2094+
matched := r.Match(req, match)
2095+
if matched {
2096+
t.Error("Should not have matched route for methods")
2097+
}
2098+
if match.MatchErr != ErrNotFound {
2099+
t.Error("Should have ErrNotFound error. Found:", match.MatchErr)
2100+
}
2101+
})
2102+
2103+
t.Run("A mismach method of a valid path should return ErrMethodMismatch", func(t *testing.T) {
2104+
r := NewRouter()
2105+
r.HandleFunc("/api2", emptyHandler).Methods("POST")
2106+
req, _ := http.NewRequest("GET", "http://localhost/api2", nil)
2107+
match := new(RouteMatch)
2108+
matched := r.Match(req, match)
2109+
if matched {
2110+
t.Error("Should not have matched route for methods")
2111+
}
2112+
if match.MatchErr != ErrMethodMismatch {
2113+
t.Error("Should have ErrMethodMismatch error. Found:", match.MatchErr)
2114+
}
2115+
})
2116+
2117+
}
2118+
20722119
func TestErrMatchNotFound(t *testing.T) {
20732120
emptyHandler := func(w http.ResponseWriter, r *http.Request) {}
20742121

‎route.go

+10
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
6666

6767
matchErr = nil // nolint:ineffassign
6868
return false
69+
} else {
70+
// Multiple routes may share the same path but use different HTTP methods. For instance:
71+
// Route 1: POST "/users/{id}".
72+
// Route 2: GET "/users/{id}", parameters: "id": "[0-9]+".
73+
//
74+
// The router must handle these cases correctly. For a GET request to "/users/abc" with "id" as "-2",
75+
// The router should return a "Not Found" error as no route fully matches this request.
76+
if match.MatchErr == ErrMethodMismatch {
77+
match.MatchErr = nil
78+
}
6979
}
7080
}
7181

0 commit comments

Comments
 (0)
Please sign in to comment.