Repository: getkin/kin-openapi
Pull request #161 (2019-12-26 09:58:30)

Throw 404 if no pathItem, 405 if pathItem has no operation
Throw 404 error if no pathItem found, throw 405 if pathItem has no operation

ErrorBoi: This PR is a fix of [this issue](https://github.com/getkin/kin-openapi/issues/158), have no rights to reopen it.
fenollp: Ah! Sorry about that. Could you modify at least one test in router_test.go to explicitly check for the error message?

PR looks good. I’ll merge once regression test is in. 
ErrorBoi: As far as I see, we might get "Path was not found", "Method not allowed" and "Doesn't match any server", so I added error handling for them in router_test.go. 

Patch:
diff --git a/openapi3filter/router.go b/openapi3filter/router.go
index 91487d6..3904750 100644
--- a/openapi3filter/router.go
+++ b/openapi3filter/router.go
@@ -178,10 +178,19 @@ func (router *Router) FindRoute(method string, url *url.URL) (*Route, map[string
 		route, _ = node.Value.(*Route)
 	}
 	if route == nil {
+		pathItem := swagger.Paths[remainingPath]
+		if pathItem == nil {
+			return nil, nil, &RouteError{
+				Route: Route{
+					Swagger: swagger,
+					Server:  server,
+				},
+				Reason: "Path was not found",
+			}
+		}
 
 		// Get operation
-		pathItem := swagger.Paths[remainingPath]
-		if pathItem == nil || pathItem.GetOperation(method) == nil {
+		if pathItem.GetOperation(method) == nil {
 			return nil, nil, &RouteError{
 				Route: Route{
 					Swagger: swagger,
@@ -191,13 +200,6 @@ func (router *Router) FindRoute(method string, url *url.URL) (*Route, map[string
 			}
 		}
 
-		return nil, nil, &RouteError{
-			Route: Route{
-				Swagger: swagger,
-				Server:  server,
-			},
-			Reason: "Path was not found",
-		}
 	}
 
 	if pathParams == nil {


Test patch:
diff --git a/openapi3filter/router_test.go b/openapi3filter/router_test.go
index 9f67660..f78370c 100644
--- a/openapi3filter/router_test.go
+++ b/openapi3filter/router_test.go
@@ -11,6 +11,12 @@ import (
 )
 
 func TestRouter(t *testing.T) {
+	var (
+		pathNotFound = "Path was not found"
+		methodNotAllowed = "Path doesn't support the HTTP method"
+		doesNotMatchAnyServer = "Does not match any server"
+	)
+
 	// Build swagger
 	helloCONNECT := &openapi3.Operation{Responses: make(openapi3.Responses)}
 	helloDELETE := &openapi3.Operation{Responses: make(openapi3.Responses)}
@@ -22,6 +28,7 @@ func TestRouter(t *testing.T) {
 	helloPUT := &openapi3.Operation{Responses: make(openapi3.Responses)}
 	helloTRACE := &openapi3.Operation{Responses: make(openapi3.Responses)}
 	paramsGET := &openapi3.Operation{Responses: make(openapi3.Responses)}
+	partialGET := &openapi3.Operation{Responses: make(openapi3.Responses)}
 	swagger := &openapi3.Swagger{
 		OpenAPI: "3.0.0",
 		Info: &openapi3.Info{
@@ -46,6 +53,9 @@ func TestRouter(t *testing.T) {
 			"/params/{x}/{y}/{z*}": &openapi3.PathItem{
 				Get: paramsGET,
 			},
+			"/partial": &openapi3.PathItem{
+				Get: partialGET,
+			},
 		},
 	}
 
@@ -59,15 +69,36 @@ func TestRouter(t *testing.T) {
 		route, pathParams, err := router.FindRoute(req.Method, req.URL)
 		if err != nil {
 			if operation == nil {
-				return
+				if err.Error() == doesNotMatchAnyServer {
+					return
+				}
+
+				pathItem := swagger.Paths[uri]
+				if pathItem == nil {
+					if err.Error() != pathNotFound {
+						t.Fatalf("'%s %s': should have returned '%s', but it returned an error: %v",
+							method, uri, pathNotFound, err)
+					}
+					return
+				}
+				if pathItem.GetOperation(method) == nil {
+					if err.Error() != methodNotAllowed {
+						t.Fatalf("'%s %s': should have returned '%s', but it returned an error: %v",
+							method, uri, methodNotAllowed, err)
+					}
+				}
+			} else {
+				t.Fatalf("'%s %s': should have returned an operation, but it returned an error: %v",
+					method, uri, err)
 			}
-			t.Fatalf("'%s %s': should have returned an operation, but it returned an error: %v",
-				method, uri, err)
 		}
-		if operation == nil {
+		if operation == nil && err == nil {
 			t.Fatalf("'%s %s': should have returned an error, but didn't",
 				method, uri)
 		}
+		if route == nil {
+			return
+		}
 		if route.Operation != operation {
 			t.Fatalf("'%s %s': Returned wrong operation (%v)",
 				method, uri, route.Operation)
@@ -109,6 +140,7 @@ func TestRouter(t *testing.T) {
 		"y": "b",
 		"z": "c/d",
 	})
+	expect("POST", "/partial", nil, nil)
 	swagger.Servers = append(swagger.Servers, &openapi3.Server{
 		URL: "https://www.example.com/api/v1/",
 	}, &openapi3.Server{