diff --git a/openapi_core/contrib/falcon/requests.py b/openapi_core/contrib/falcon/requests.py index 08ee24b..9bb19d9 100644 --- a/openapi_core/contrib/falcon/requests.py +++ b/openapi_core/contrib/falcon/requests.py @@ -23,9 +23,9 @@ class FalconOpenAPIRequestFactory: cookie=req.cookies, ) return OpenAPIRequest( - host_url=req.host, + host_url=None, path=req.path, - path_pattern=req.uri_template, + path_pattern=req.uri_template or req.path, method=method, parameters=parameters, # Support falcon-jsonify. diff --git a/requirements_dev.txt b/requirements_dev.txt index d96c287..1f282d6 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -2,6 +2,7 @@ mock==2.0.0 pytest==3.5.0 pytest-flake8 pytest-cov==2.5.1 +falcon==2.0.0 flask django==2.2.10; python_version>="3.0" requests==2.22.0 diff --git a/setup.cfg b/setup.cfg index c181fac..564a212 100644 --- a/setup.cfg +++ b/setup.cfg @@ -38,6 +38,7 @@ tests_require = pytest pytest-flake8 pytest-cov + falcon flask webob diff --git a/tests/integration/contrib/falcon/conftest.py b/tests/integration/contrib/falcon/conftest.py new file mode 100644 index 0000000..af6155b --- /dev/null +++ b/tests/integration/contrib/falcon/conftest.py @@ -0,0 +1,49 @@ +from falcon import Request, Response +from falcon.routing import DefaultRouter +from falcon.testing import create_environ +import pytest +from six import BytesIO + + +@pytest.fixture +def environ_factory(): + def create_env(method, path, server_name): + return create_environ( + host=server_name, + path=path, + ) + return create_env + + +@pytest.fixture +def router(): + router = DefaultRouter() + router.add_route('/browse//', None) + return router + + +@pytest.fixture +def request_factory(environ_factory, router): + server_name = 'localhost' + + def create_request(method, path, subdomain=None, query_string=None): + environ = environ_factory(method, path, server_name) + options = None + # return create_req(options=options, **environ) + req = Request(environ, options) + req.uri_template = router.find(path, req) + return req + return create_request + + +@pytest.fixture +def response_factory(environ_factory): + def create_response( + data, status_code=200, content_type='application/json'): + options = { + 'content_type': content_type, + 'data': data, + 'status': status_code, + } + return Response(options) + return create_response diff --git a/tests/integration/contrib/falcon/data/v3.0/falcon_factory.yaml b/tests/integration/contrib/falcon/data/v3.0/falcon_factory.yaml new file mode 100644 index 0000000..6ed6d56 --- /dev/null +++ b/tests/integration/contrib/falcon/data/v3.0/falcon_factory.yaml @@ -0,0 +1,48 @@ +openapi: "3.0.0" +info: + title: Basic OpenAPI specification used with test_flask.TestFlaskOpenAPIIValidation + version: "0.1" +servers: + - url: 'http://localhost' +paths: + '/browse/{id}/': + parameters: + - name: id + in: path + required: true + description: the ID of the resource to retrieve + schema: + type: integer + get: + responses: + 200: + description: Return the resource. + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: string + default: + description: Return errors. + content: + application/json: + schema: + type: object + required: + - errors + properties: + errors: + type: array + items: + type: object + properties: + title: + type: string + code: + type: string + message: + type: string diff --git a/tests/integration/contrib/falcon/test_falcon_validation.py b/tests/integration/contrib/falcon/test_falcon_validation.py new file mode 100644 index 0000000..cec3631 --- /dev/null +++ b/tests/integration/contrib/falcon/test_falcon_validation.py @@ -0,0 +1,36 @@ +import pytest + +from openapi_core.contrib.falcon.requests import FalconOpenAPIRequestFactory +from openapi_core.contrib.falcon.responses import FalconOpenAPIResponseFactory +from openapi_core.shortcuts import create_spec +from openapi_core.validation.request.validators import RequestValidator +from openapi_core.validation.response.validators import ResponseValidator + + +class TestFalconOpenAPIValidation(object): + + @pytest.fixture + def spec(self, factory): + specfile = 'contrib/falcon/data/v3.0/falcon_factory.yaml' + return create_spec(factory.spec_from_file(specfile)) + + def test_response_validator_path_pattern(self, + spec, + request_factory, + response_factory): + validator = ResponseValidator(spec) + request = request_factory('GET', '/browse/12/', subdomain='kb') + openapi_request = FalconOpenAPIRequestFactory.create( + request, '/browse/12/') + response = response_factory('{"data": "data"}', status_code=200) + openapi_response = FalconOpenAPIResponseFactory.create(response) + result = validator.validate(openapi_request, openapi_response) + assert not result.errors + + def test_request_validator_path_pattern(self, spec, request_factory): + validator = RequestValidator(spec) + request = request_factory('GET', '/browse/12/', subdomain='kb') + openapi_request = FalconOpenAPIRequestFactory.create( + request, '/browse/12/') + result = validator.validate(openapi_request) + assert not result.errors