Skip to content

Commit f21cdce

Browse files
committed
fix: return HTTP 405 when request method mismatch
When a route is correctly matched, but the HTTP method used does not, we should return an HTTP 405 Method Not Allowed. However, in our previous implementation, we would always return an HTTP 404 Not Found, which is incorrect. Instead, we can match on whether we have received an `ErrMethodNotAllowed` and if so, return the correct HTTP 405.
1 parent 4c9895d commit f21cdce

3 files changed

Lines changed: 30 additions & 0 deletions

File tree

oapi_validate.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ func ValidateRequestFromContext(ctx echo.Context, router routers.Router, options
124124

125125
// We failed to find a matching route for the request.
126126
if err != nil {
127+
if errors.Is(err, routers.ErrMethodNotAllowed) {
128+
return echo.NewHTTPError(http.StatusMethodNotAllowed)
129+
}
130+
127131
switch e := err.(type) {
128132
case *routers.RouteError:
129133
// We've got a bad request, the path requested doesn't match

oapi_validate_example_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,20 @@ components:
140140
logResponseBody(rr)
141141
fmt.Println()
142142

143+
// ================================================================================
144+
fmt.Println("# A request that uses the wrong HTTP method is rejected with HTTP 405 Method Not Allowed")
145+
req, err = http.NewRequest(http.MethodDelete, "/resource", bytes.NewReader(data))
146+
must(err)
147+
req.Header.Set("Content-Type", "application/json")
148+
149+
rr = httptest.NewRecorder()
150+
151+
e.ServeHTTP(rr, req)
152+
153+
fmt.Printf("Received an HTTP %d response. Expected HTTP 405\n", rr.Code)
154+
logResponseBody(rr)
155+
fmt.Println()
156+
143157
// ================================================================================
144158
fmt.Println("# A request that is well-formed is passed through to the Handler")
145159
body = map[string]string{
@@ -184,6 +198,10 @@ components:
184198
// Received an HTTP 400 response. Expected HTTP 400
185199
// Response body: {"message":"request body has an error: doesn't match schema: property \"invalid\" is unsupported"}
186200
//
201+
// # A request that uses the wrong HTTP method is rejected with HTTP 405 Method Not Allowed
202+
// Received an HTTP 405 response. Expected HTTP 405
203+
// Response body: {"message":"Method Not Allowed"}
204+
//
187205
// # A request that is well-formed is passed through to the Handler
188206
// POST /resource was called
189207
// Received an HTTP 204 response. Expected HTTP 204

oapi_validate_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,14 @@ func TestOapiRequestValidator(t *testing.T) {
146146
called = false
147147
}
148148

149+
// Send a request with the wrong HTTP method
150+
{
151+
rec := doPost(t, e, "http://deepmap.ai/multiparamresource", nil)
152+
assert.Equal(t, http.StatusMethodNotAllowed, rec.Code)
153+
assert.False(t, called, "Handler should not have been called")
154+
called = false
155+
}
156+
149157
// Add a handler for the POST message
150158
e.POST("/resource", func(c echo.Context) error {
151159
called = true

0 commit comments

Comments
 (0)