Repository: striglia/pyramid_swagger (python)

Issue:
Be more precise with which 4xx error is raised
Validation currently raises HTTP 400s when 1) a route is not matched in the spec and 2) a route is matched but validation fails. This is better than nothing, but not quite semantically correct.

The missing route should definitely return a 404, and the failed validation can return either 400 or 422 (see http://www.bennadel.com/blog/2434-http-status-codes-for-invalid-data-400-vs-422.htm for details).


Pull request description:
Return a 404 when a path cannot be found in the Swagger spec
We'll only do this if path validation is turned on; otherwise Pyramid itself will return a 404 if no matching route is registered. So not only does the 404 make more sense, it also better fits with what Pyramid does.

During testing I uncovered that the `test_400_if_extra_body_args` uses the wrong URL, that test all of a sudden also started returning a 404. This is because the correct URL is `/sample`, not `/sample_post`.

This partially fixes #2.

Patch:
diff --git a/pyramid_swagger/exceptions.py b/pyramid_swagger/exceptions.py
index b1d9b51..20b5b9a 100644
--- a/pyramid_swagger/exceptions.py
+++ b/pyramid_swagger/exceptions.py
@@ -4,12 +4,17 @@ import sys
 import six
 from pyramid.httpexceptions import HTTPBadRequest
 from pyramid.httpexceptions import HTTPInternalServerError
+from pyramid.httpexceptions import HTTPNotFound
 
 
 class RequestValidationError(HTTPBadRequest):
     pass
 
 
+class PathNotFoundError(HTTPNotFound):
+    pass
+
+
 class ResponseValidationError(HTTPInternalServerError):
     pass
 
diff --git a/pyramid_swagger/tween.py b/pyramid_swagger/tween.py
index d486f8c..c14cea0 100644
--- a/pyramid_swagger/tween.py
+++ b/pyramid_swagger/tween.py
@@ -19,6 +19,7 @@ from bravado_core.response import get_response_spec
 from bravado_core.response import OutgoingResponse
 from pyramid.interfaces import IRoutesMapper
 
+from pyramid_swagger.exceptions import PathNotFoundError
 from pyramid_swagger.exceptions import RequestValidationError
 from pyramid_swagger.exceptions import ResponseValidationError
 from pyramid_swagger.model import PathNotMatchedError
@@ -165,7 +166,7 @@ def validation_tween_factory(handler, registry):
         except PathNotMatchedError as exc:
             if settings.validate_path:
                 with validation_context(request):
-                    raise RequestValidationError(str(exc))
+                    raise PathNotFoundError(str(exc))
             else:
                 return handler(request)
 


Test patch:
diff --git a/tests/acceptance/request_test.py b/tests/acceptance/request_test.py
index 97dc137..91735c7 100644
--- a/tests/acceptance/request_test.py
+++ b/tests/acceptance/request_test.py
@@ -98,11 +98,11 @@ def test_200_if_request_arg_types_are_not_strings(test_app):
     ).status_code == 200
 
 
-def test_400_if_path_not_in_swagger(test_app):
+def test_404_if_path_not_in_swagger(test_app):
     assert test_app.get(
         '/does_not_exist',
         expect_errors=True,
-    ).status_code == 400
+    ).status_code == 404
 
 
 def test_400_if_request_arg_is_wrong_type_but_not_castable(test_app):
@@ -176,7 +176,7 @@ def test_200_if_required_body_is_primitives(test_app):
 
 def test_400_if_extra_body_args(test_app):
     assert test_app.post_json(
-        '/sample_post',
+        '/sample',
         {'foo': 'test', 'bar': 'test', 'made_up_argument': 1},
         expect_errors=True,
     ).status_code == 400