Repository: gorilla/mux (go)

Issue:
[bug] Adding to GET the same endpoint with POST and different Queries ends up with inconsistent error messages
**Describe the bug**
Adding the same endpoint POST with different Queries ends up with incosnsistent error messages


**Versions**
 Go version: 1.18



**Steps to Reproduce**
Playground: https://go.dev/play/p/xzoAkpEhGgy

```go
// You can edit this code!
// Click here and start typing.
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"time"

	"github.com/gorilla/mux"
)

func main() {

	r := mux.NewRouter()

	r.HandleFunc("/api/v2", func(w http.ResponseWriter, r *http.Request) {
		// an example API handler
		fmt.Fprintf(w, "You made a POST request")
		json.NewEncoder(w).Encode(map[string]bool{"ok": true})
	}).Methods("POST")

	r.HandleFunc("/api/v2", func(w http.ResponseWriter, r *http.Request) {
		// an example API handler
		fmt.Fprintf(w, "You made a GET request")
		json.NewEncoder(w).Encode(map[string]bool{"ok": true})
	}).
		Queries("from", "{from:[0-9]+}",
			"to", "{to:[0-9]+}").Methods("GET")


	srv := &http.Server{
		Handler: r,
		Addr:    "127.0.0.1:8000",
		// Good practice: enforce timeouts for servers you create!
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
	}
	go srv.ListenAndServe()


	req2 := httptest.NewRequest("GET", "/api/v2?from=3&to=-5", nil)
	out2 := httptest.NewRecorder()

	r.ServeHTTP(out2, req2)

	fmt.Println(out2.Code)
	fmt.Println(out2)

}
```

ENDS with the result, I was expecting 404:
```go
405
```
HOWEVER

When I remove the POST request 
playground: https://go.dev/play/p/EXiF00_WrFW

```go
// You can edit this code!
// Click here and start typing.
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"time"

	"github.com/gorilla/mux"
)

func main() {

	r := mux.NewRouter()

	r.HandleFunc("/api/v2", func(w http.ResponseWriter, r *http.Request) {
		// an example API handler
		fmt.Fprintf(w, "You made a GET request")
		json.NewEncoder(w).Encode(map[string]bool{"ok": true})
	}).
		Queries("from", "{from:[0-9]+}",
			"to", "{to:[0-9]+}").Methods("GET")


	srv := &http.Server{
		Handler: r,
		Addr:    "127.0.0.1:8000",
		// Good practice: enforce timeouts for servers you create!
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
	}
	go srv.ListenAndServe()


	req2 := httptest.NewRequest("GET", "/api/v2?from=3&to=-5", nil)
	out2 := httptest.NewRecorder()

	r.ServeHTTP(out2, req2)

	fmt.Println(out2.Code)

}
```

Result is
```go
 404
```


**Expected behavior**
Both cases should end in only 404-s


…


Pull request:
[BUG] Inconsistent HTTP status code on query mismatch
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: https://github.com/gorilla/mux/issues/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!


Patch:
diff --git a/route.go b/route.go
index ce1c9bf..abea99b 100644
--- a/route.go
+++ b/route.go
@@ -66,6 +66,16 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
 
 			matchErr = nil // nolint:ineffassign
 			return false
+		} else {
+			// Multiple routes may share the same path but use different HTTP methods. For instance:
+			// Route 1: POST "/users/{id}".
+			// Route 2: GET "/users/{id}", parameters: "id": "[0-9]+".
+			//
+			// The router must handle these cases correctly. For a GET request to "/users/abc" with "id" as "-2",
+			// The router should return a "Not Found" error as no route fully matches this request.
+			if match.MatchErr == ErrMethodMismatch {
+				match.MatchErr = nil
+			}
 		}
 	}
 


Test patch:
diff --git a/mux_test.go b/mux_test.go
index 4345254..bd97d33 100644
--- a/mux_test.go
+++ b/mux_test.go
@@ -2069,6 +2069,53 @@ func TestNoMatchMethodErrorHandler(t *testing.T) {
 	}
 }
 
+func TestMultipleDefinitionOfSamePathWithDifferentMethods(t *testing.T) {
+	emptyHandler := func(w http.ResponseWriter, r *http.Request) {}
+
+	r := NewRouter()
+	r.HandleFunc("/api", emptyHandler).Methods("POST")
+	r.HandleFunc("/api", emptyHandler).Queries("time", "{time:[0-9]+}").Methods("GET")
+
+	t.Run("Post Method should be matched properly", func(t *testing.T) {
+		req, _ := http.NewRequest("POST", "http://localhost/api", nil)
+		match := new(RouteMatch)
+		matched := r.Match(req, match)
+		if !matched {
+			t.Error("Should have matched route for methods")
+		}
+		if match.MatchErr != nil {
+			t.Error("Should not have any matching error. Found:", match.MatchErr)
+		}
+	})
+
+	t.Run("Get Method with invalid query value should not match", func(t *testing.T) {
+		req, _ := http.NewRequest("GET", "http://localhost/api?time=-4", nil)
+		match := new(RouteMatch)
+		matched := r.Match(req, match)
+		if matched {
+			t.Error("Should not have matched route for methods")
+		}
+		if match.MatchErr != ErrNotFound {
+			t.Error("Should have ErrNotFound error. Found:", match.MatchErr)
+		}
+	})
+
+	t.Run("A mismach method of a valid path should return ErrMethodMismatch", func(t *testing.T) {
+		r := NewRouter()
+		r.HandleFunc("/api2", emptyHandler).Methods("POST")
+		req, _ := http.NewRequest("GET", "http://localhost/api2", nil)
+		match := new(RouteMatch)
+		matched := r.Match(req, match)
+		if matched {
+			t.Error("Should not have matched route for methods")
+		}
+		if match.MatchErr != ErrMethodMismatch {
+			t.Error("Should have ErrMethodMismatch error. Found:", match.MatchErr)
+		}
+	})
+
+}
+
 func TestErrMatchNotFound(t *testing.T) {
 	emptyHandler := func(w http.ResponseWriter, r *http.Request) {}