Ejemplo n.º 1
0
    def test_hosts(self, factory, server, spec_path):
        spec_dict = factory.spec_from_file(spec_path)
        spec = create_spec(spec_dict)
        validator = RequestValidator(spec)
        request = MockRequest(server, "get", "/status")

        result = validator.validate(request)

        assert not result.errors
Ejemplo n.º 2
0
    def test_param_present(self, factory, spec_path):
        spec_dict = factory.spec_from_file(spec_path)
        spec = create_spec(spec_dict)

        path = spec['/resource/{resId}']

        assert len(path.parameters) == 1
        param = path.parameters['resId']
        assert param.required
        assert param.location == ParameterLocation.PATH
Ejemplo n.º 3
0
    def test_get_object_failure(self, factory, response, spec_path):
        spec_dict = factory.spec_from_file(spec_path)
        spec = create_spec(spec_dict)
        request = MockRequest("http://www.example.com", "get",
                              "/object/{objectId}")

        validator = ResponseValidator(spec)
        response = MockResponse(data=json.dumps(response))

        result = validator.validate(request, response)
        assert result.errors
Ejemplo n.º 4
0
    def test_post_object_success(self, factory, response, spec_path):
        spec_dict = factory.spec_from_file(spec_path)
        spec = create_spec(spec_dict)
        validator = RequestValidator(spec)
        request = MockRequest("http://www.example.com",
                              "post",
                              "/object",
                              data=json.dumps(response))

        result = validator.validate(request)
        assert not result.errors
Ejemplo n.º 5
0
    def test_invalid_operation(self, factory, server, spec_path):
        spec_dict = factory.spec_from_file(spec_path)
        spec = create_spec(spec_dict)
        validator = RequestValidator(spec)
        request = MockRequest(server, "get", "/nonexistent")

        result = validator.validate(request)

        assert len(result.errors) == 1
        assert isinstance(result.errors[0], InvalidOperation)
        assert result.body is None
        assert result.parameters == {}
Ejemplo n.º 6
0
    def test_invalid_operation(self, factory, server, spec_path):
        spec_dict = factory.spec_from_file(spec_path)
        spec = create_spec(spec_dict)
        validator = RequestValidator(spec)
        request = MockRequest(server, "post", "/status")

        result = validator.validate(request)

        assert len(result.errors) == 1
        assert isinstance(result.errors[0], OperationNotFound)
        assert result.body is None
        assert result.parameters == RequestParameters()
Ejemplo n.º 7
0
    def test_param_present(self, factory, spec_path):
        spec_dict = factory.spec_from_file(spec_path)
        spec = create_spec(spec_dict)

        path = spec / "paths#/resource/{resId}"

        parameters = path / "parameters"
        assert len(parameters) == 1

        param = parameters[0]
        assert param["name"] == "resId"
        assert param["required"]
        assert param["in"] == "path"
Ejemplo n.º 8
0
    def test_param_present(self, factory, spec_path):
        spec_dict = factory.spec_from_file(spec_path)
        spec = create_spec(spec_dict)

        path = spec / 'paths#/resource/{resId}'

        parameters = path / 'parameters'
        assert len(parameters) == 1

        param = parameters[0]
        assert param['name'] == 'resId'
        assert param['required']
        assert param['in'] == 'path'
Ejemplo n.º 9
0
    def test_no_param(self, factory):
        spec_dict = factory.spec_from_file("data/v3.0/links.yaml")
        spec = create_spec(spec_dict)
        resp = spec['/status']['get'].responses['default']

        assert len(resp.links) == 1

        link = resp.links['noParamLink']

        assert link.operationId == 'noParOp'
        assert link.server is None
        assert link.request_body is None
        assert len(link.parameters) == 0
Ejemplo n.º 10
0
    def test_no_param(self, factory):
        spec_dict = factory.spec_from_file("data/v3.0/links.yaml")
        spec = create_spec(spec_dict)
        resp = spec / "paths#/status#get#responses#default"

        links = resp / "links"
        assert len(links) == 1

        link = links / "noParamLink"
        assert link["operationId"] == "noParOp"
        assert "server" not in link
        assert "requestBody" not in link
        assert "parameters" not in link
Ejemplo n.º 11
0
    def test_no_param(self, factory):
        spec_dict = factory.spec_from_file("data/v3.0/links.yaml")
        spec = create_spec(spec_dict)
        resp = spec / 'paths#/status#get#responses#default'

        links = resp / 'links'
        assert len(links) == 1

        link = links / 'noParamLink'
        assert link['operationId'] == 'noParOp'
        assert 'server' not in link
        assert 'requestBody' not in link
        assert 'parameters' not in link
Ejemplo n.º 12
0
def main():
    global app
    specfile = "./apis/api.yaml"
    specurl = "file://" + abspath(specfile)
    specdict = read_yaml_file(specfile)
    openapi_spec = create_spec(specdict, spec_url=specurl)

    openapi_middleware = FalconOpenAPIMiddleware.from_spec(openapi_spec)

    app = API(middleware=[openapi_middleware])

    auth_server = Auth()
    user_server = User()

    app.add_route('/user', user_server)
    app.add_route('/token', auth_server)
Ejemplo n.º 13
0
    def test_param(self, factory):
        spec_dict = factory.spec_from_file("data/v3.0/links.yaml")
        spec = create_spec(spec_dict)
        resp = spec['/status/{resourceId}']['get'].responses['default']

        assert len(resp.links) == 1

        link = resp.links['paramLink']

        assert link.operationId == 'paramOp'
        assert link.server is None
        assert link.request_body == 'test'
        assert len(link.parameters) == 1

        param = link.parameters['opParam']

        assert param == '$request.path.resourceId'
Ejemplo n.º 14
0
    def test_param(self, factory):
        spec_dict = factory.spec_from_file("data/v3.0/links.yaml")
        spec = create_spec(spec_dict)
        resp = spec / "paths#/status/{resourceId}#get#responses#default"

        links = resp / "links"
        assert len(links) == 1

        link = links / "paramLink"
        assert link["operationId"] == "paramOp"
        assert "server" not in link
        assert link["requestBody"] == "test"

        parameters = link["parameters"]
        assert len(parameters) == 1

        param = parameters["opParam"]
        assert param == "$request.path.resourceId"
Ejemplo n.º 15
0
    def test_request_override_param(self, spec_dict):
        # override path parameter on operation
        spec_dict["paths"]["/resource"]["get"]["parameters"] = [{
            # full valid parameter object required
            "name": "resId",
            "in": "query",
            "required": False,
            "schema": {
                "type": "integer",
            },
        }]
        validator = RequestValidator(create_spec(spec_dict))
        request = MockRequest('http://example.com', 'get', '/resource')
        result = validator.validate(request)

        assert len(result.errors) == 0
        assert result.body is None
        assert result.parameters == {}
Ejemplo n.º 16
0
    def test_param(self, factory):
        spec_dict = factory.spec_from_file("data/v3.0/links.yaml")
        spec = create_spec(spec_dict)
        resp = spec / 'paths#/status/{resourceId}#get#responses#default'

        links = resp / 'links'
        assert len(links) == 1

        link = links / 'paramLink'
        assert link['operationId'] == 'paramOp'
        assert 'server' not in link
        assert link['requestBody'] == 'test'

        parameters = link['parameters']
        assert len(parameters) == 1

        param = parameters['opParam']
        assert param == '$request.path.resourceId'
Ejemplo n.º 17
0
    def test_request_override_param_uniqueness(self, spec_dict):
        # add parameter on operation with same name as on path but
        # different location
        spec_dict["paths"]["/resource"]["get"]["parameters"] = [{
            # full valid parameter object required
            "name": "resId",
            "in": "header",
            "required": False,
            "schema": {
                "type": "integer",
            },
        }]
        validator = RequestValidator(create_spec(spec_dict))
        request = MockRequest('http://example.com', 'get', '/resource')
        result = validator.validate(request)

        assert len(result.errors) == 1
        assert type(result.errors[0]) == MissingRequiredParameter
        assert result.body is None
        assert result.parameters == {}
Ejemplo n.º 18
0
 def flask_spec(self, factory):
     specfile = 'data/v3.0/flask_factory.yaml'
     return create_spec(factory.spec_from_file(specfile))
Ejemplo n.º 19
0
 def spec(self, spec_dict):
     return create_spec(spec_dict)
Ejemplo n.º 20
0
def setup_openapi(
    app: web.Application,
    schema_path: Union[str, Path],
    *operations: OperationTableDef,
    route_prefix: str = None,
    is_validate_response: bool = False,
    has_openapi_schema_handler: bool = True,
) -> None:
    """Setup OpenAPI schema to use with aiohttp.web application.

    Unlike `aiohttp-apispec <https://aiohttp-apispec.readthedocs.io/>`_ and
    other tools, which provides OpenAPI/Swagger support for aiohttp.web
    applications, ``rororo`` changes the way of using OpenAPI schema with
    ``aiohttp.web`` apps.

    ``rororo`` relies on concrete OpenAPI schema file, path to which need to be
    registered on application startup (mostly inside of ``create_app`` factory
    or right after :class:`aiohttp.web.Application` instantiation).

    And as valid OpenAPI schema ensure unique ``operationId`` used accross the
    schema ``rororo`` uses them as a key while telling aiohttp.web to use given
    view handler for serving required operation.

    With that in mind registering (setting up) OpenAPI schema requires:

    1. :class:`aiohttp.web.Application` instance
    2. Path to file (json or yaml) with OpenAPI schema
    3. OpenAPI operation handlers mapping (rororo's equialent of
       :class:`aiohttp.web.RouteTableDef`)

    In common cases setup looks like,

    .. code-block:: python

        from pathlib import Path
        from typing import List

        from aiohttp import web

        from .views import operations


        def create_app(argv: List[str] = None) -> web.Application:
            app = web.Application()
            setup_openapi(
                app,
                Path(__file__).parent / 'openapi.yaml',
                operations
            )
            return app

    It is also possible to setup route prefix to use if server URL inside of
    your OpenAPI schema ends with path, like ``http://yourserver.url/api``.
    For that cases you need to pass ``'/api'`` as a ``route_prefix`` keyword
    argument.

    By default, ``rororo`` will not validate operation responses against
    OpenAPI schema due to performance reasons. To enable this feature, pass
    ``is_validate_response`` truthy flag.

    By default, ``rororo`` will share the OpenAPI schema which is registered
    for your aiohttp.web application. In case if you don't want to share this
    schema, pass ``has_openapi_schema_handler=False`` on setting up OpenAPI.
    """
    def read_schema(path: Path) -> DictStrAny:
        content = path.read_text()
        if path.suffix == ".json":
            return json.loads(content)

        if path.suffix in {".yml", ".yaml"}:
            return yaml.safe_load(content)

        raise ConfigurationError(
            f"Unsupported OpenAPI schema file: {path}. At a moment rororo "
            "supports loading OpenAPI schemas from: .json, .yml, .yaml files")

    # Ensure OpenAPI schema is a readable file
    path = Path(schema_path) if isinstance(schema_path, str) else schema_path
    if not path.exists() or not path.is_file():
        uid = os.getuid()
        raise ConfigurationError(
            f"Unable to find OpenAPI schema file at {path}. Please check that "
            "file exists at given path and readable by current user ID: "
            f"{uid}")

    # Store OpenAPI schema dict in the application dict
    app[OPENAPI_SCHEMA_APP_KEY] = oas = read_schema(path)

    # Create the spec and put it to the application dict as well
    try:
        app[OPENAPI_SPEC_APP_KEY] = create_spec(oas)
    except OpenAPIValidationError:
        raise ConfigurationError(
            f"Unable to load valid OpenAPI schema in {path}. In most cases "
            "it means that given file doesn't contain valid OpenAPI 3 schema. "
            "To get full details about errors run `openapi-spec-validator "
            f"{path}`")

    # Store whether rororo need to validate response or not. By default: not
    app[OPENAPI_IS_VALIDATE_RESPONSE_APP_KEY] = is_validate_response

    # Register all operation handlers to web application
    for item in operations:
        app.router.add_routes(
            convert_operations_to_routes(item, oas, prefix=route_prefix))

    # Register the route to dump openapi schema used for the application if
    # required
    if has_openapi_schema_handler:
        app.router.add_get(
            add_prefix("/openapi.{schema_format}", route_prefix),
            views.openapi_schema,
        )
Ejemplo n.º 21
0
 def spec(self, factory):
     specfile = 'contrib/falcon/data/v3.0/falcon_factory.yaml'
     return create_spec(factory.spec_from_file(specfile))
Ejemplo n.º 22
0
def spec(factory):
    spec_dict = factory.spec_from_file("data/v3.0/read_only_write_only.yaml")
    return create_spec(spec_dict)
def spec(factory):
    spec_dict = factory.spec_from_file("data/v3.0/security_override.yaml")
    return create_spec(spec_dict)
Ejemplo n.º 24
0
 def django_spec(self, factory):
     specfile = 'data/v3.0/django_factory.yaml'
     return create_spec(factory.spec_from_file(specfile))
Ejemplo n.º 25
0
 def spec(self, spec_dict, spec_uri):
     return create_spec(spec_dict, spec_uri)
Ejemplo n.º 26
0
 def spec(self, factory):
     specfile = "contrib/flask/data/v3.0/flask_factory.yaml"
     return create_spec(factory.spec_from_file(specfile))
 def spec(self, factory):
     specfile = 'contrib/requests/data/v3.0/requests_factory.yaml'
     return create_spec(factory.spec_from_file(specfile))
Ejemplo n.º 28
0
 def test_raises_on_invalid(self, spec_dict):
     with pytest.raises(ValidationError):
         create_spec(spec_dict)