Пример #1
0
def create_and_validate_request(endpoint,
                                method,
                                payload='',
                                params=[],
                                headers=[]):
    """
    Helper function to create OpenAPIRequest and validate it
    :param endpoint: API endpoint
    :param method: API request method
    :param payload: API request payload
    :param params: API request payload
    :param headers: API request headers
    :return:
        - request: OpenAPIRequest
        - request_result: result of request validation
    """
    parameters = RequestParameters(query=ImmutableMultiDict(params),
                                   path=endpoint,
                                   header=headers)

    request = OpenAPIRequest(
        full_url_pattern=endpoint,
        method=method,
        parameters=parameters,
        body=payload,
        mimetype='application/json',
    )

    validator = RequestValidator(spec)
    request_result = validator.validate(request)

    return request, request_result
Пример #2
0
def validate_data(path, request, response, validate_request,
                  validate_response):
    if response.status_code == status.HTTP_405_METHOD_NOT_ALLOWED:
        return

    spec = _load_spec(resolve(path).kwargs.get('version'))
    request = DjangoOpenAPIRequestFactory.create(request)
    response = DjangoOpenAPIResponseFactory.create(response)

    # request
    if validate_request:
        validator = RequestValidator(
            spec, custom_formatters=CUSTOM_FORMATTERS)
        result = validator.validate(request)
        try:
            result.raise_for_errors()
        except OpenAPIMediaTypeError:
            if response.status_code != status.HTTP_400_BAD_REQUEST:
                raise
        except OpenAPIParameterError:
            # TODO(stephenfin): In API v2.0, this should be an error. As things
            # stand, we silently ignore these issues.
            assert response.status_code == status.HTTP_200_OK

    # response
    if validate_response:
        validator = ResponseValidator(
            spec, custom_formatters=CUSTOM_FORMATTERS)
        result = validator.validate(request, response)
        result.raise_for_errors()
Пример #3
0
 def test_request_validator_with_query(self, spec, request_factory):
     validator = RequestValidator(spec)
     request = request_factory('GET', '/browse/12',
                               query_string='detail_level=2',
                               subdomain='kb')
     openapi_request = FalconOpenAPIRequestFactory.create(request)
     result = validator.validate(openapi_request)
     assert not result.errors
Пример #4
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
Пример #5
0
 def test_request_validator_path_pattern(self, django_spec,
                                         request_factory):
     from django.urls import resolve
     validator = RequestValidator(django_spec)
     request = request_factory.get('/admin/auth/group/1/')
     request.resolver_match = resolve('/admin/auth/group/1/')
     openapi_request = DjangoOpenAPIRequest(request)
     result = validator.validate(openapi_request)
     assert not result.errors
Пример #6
0
    def test_post_object_failure(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 result.errors
Пример #7
0
async def validate_request(request: web.Request, spec: OpenApiSpec):
    """ Validates aiohttp.web.Request against an opeapi specification

    Returns parameters dict, body object and list of errors (exceptions objects)
    """
    req = await AiohttpOpenAPIRequest.create(request)

    validator = RequestValidator(spec)
    result = validator.validate(req)

    return result.parameters, result.body, result.errors
Пример #8
0
 def test_request_validator_path_pattern(self, spec):
     validator = RequestValidator(spec)
     request = requests.Request(
         'POST', 'http://localhost/browse/12/',
         params={'q': 'string'},
         headers={'content-type': 'application/json'},
         json={'param1': 1},
     )
     openapi_request = RequestsOpenAPIRequest(request)
     result = validator.validate(openapi_request)
     assert not result.errors
 def test_request_validator_path_pattern(self, spec):
     validator = RequestValidator(spec)
     request = requests.Request(
         "POST",
         "http://localhost/browse/12/",
         params={"q": "string"},
         headers={"content-type": "application/json"},
         json={"param1": 1},
     )
     openapi_request = RequestsOpenAPIRequest(request)
     result = validator.validate(openapi_request)
     assert not result.errors
Пример #10
0
    def test_invalid_path(self, factory, server, spec_path):
        spec_dict = factory.spec_from_file(spec_path)
        spec = Spec.create(spec_dict)
        validator = RequestValidator(spec)
        request = MockRequest(server, "get", "/nonexistent")

        result = validator.validate(request)

        assert len(result.errors) == 1
        assert isinstance(result.errors[0], PathNotFound)
        assert result.body is None
        assert result.parameters == Parameters()
Пример #11
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 == {}
Пример #12
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()
Пример #13
0
def validate_body(spec, request, request_factory=None):
    if request_factory is not None:
        request = request_factory(request)

    validator = RequestValidator(spec)
    result = validator.validate(request)

    try:
        result.raise_for_errors()
    except OpenAPIParameterError:
        return result.body
    else:
        return result.body
Пример #14
0
def validate_body(spec, request, wrapper_class=None):
    if wrapper_class is not None:
        request = wrapper_class(request)

    validator = RequestValidator(spec)
    result = validator.validate(request)

    try:
        result.raise_for_errors()
    except OpenAPIParameterError:
        return result.body
    else:
        return result.body
Пример #15
0
def validate_request(response):
    """Validate an API request"""
    openapi_spec = get_openapi_spec()
    validator = RequestValidator(openapi_spec)
    request = wrap_request(response.request, openapi_spec)
    result = validator.validate(request)
    print(result.errors)
    result.raise_for_errors()

    validator = ResponseValidator(openapi_spec)
    response = wrap_response(response)
    result = validator.validate(request, response)
    print(result.errors)
    result.raise_for_errors()
Пример #16
0
def sent_request(client14, container):
    path = container['request_data']['path']
    resp = client14.simulate_get('{}/spec/1.4'.format(path))
    assert HTTP_OK == resp.status
    spec = create_spec(resp.json)
    req = FalconOpenAPIWrapper(app, **container['request_data'])

    validator = RequestValidator(spec)
    result = validator.validate(req)
    assert not result.errors

    validator = ResponseValidator(spec)
    result = validator.validate(req, req)
    assert not result.errors
    container['response'] = req.request
Пример #17
0
 def reload(self) -> None:
     # Because importing yamole (and in turn, yaml) takes
     # significant time, and we only use python-yaml for our API
     # docs, importing it lazily here is a significant optimization
     # to `manage.py` startup.
     #
     # There is a bit of a race here...we may have two processes
     # accessing this module level object and both trying to
     # populate self.data at the same time.  Hopefully this will
     # only cause some extra processing at startup and not data
     # corruption.
     from yamole import YamoleParser
     with open(self.path) as f:
         yaml_parser = YamoleParser(f)
     self.data = yaml_parser.data
     validator_spec = create_spec(self.data)
     self.core_data = RequestValidator(validator_spec)
     self.create_regex_dict()
     self.last_update = os.path.getmtime(self.path)
     # Form a set of all documented events
     self.documented_events.clear()
     schema = (self.data['paths']['/events']['get']['responses']
               ['200']['content']['application/json']['schema'])
     for events in schema['properties']['events']['items']['oneOf']:
         op_str = ':'
         if 'op' in events['properties']:
             op_str = f':{events["properties"]["op"]["enum"][0]}'
         self.documented_events.add(events['properties']['type']['enum'][0]
                                    + op_str)
Пример #18
0
    def __init__(
        self,
        api_spec_path: Optional[str] = None,
        server: Optional[str] = None,
        logger: logging.Logger = _default_logger,
    ):
        """
        Initialize the API spec.

        :param api_spec_path: Directory API path and filename of the API spec YAML source file.
        """
        self._validator = None  # type: Optional[RequestValidator]
        self.logger = logger
        if api_spec_path is not None:
            try:
                api_spec_dict = read_yaml_file(api_spec_path)
                if server is not None:
                    api_spec_dict["servers"] = [{"url": server}]
                api_spec = create_spec(api_spec_dict)
                self._validator = RequestValidator(api_spec)
            except OpenAPIValidationError as e:  # pragma: nocover
                self.logger.error(
                    f"API specification YAML source file not correctly formatted: {str(e)}"
                )
            except Exception:
                self.logger.exception(
                    "API specification YAML source file not correctly formatted."
                )
                raise
Пример #19
0
def validate_parameters(spec, request, request_factory=None):
    if request_factory is not None:
        request = request_factory(request)

    validator = RequestValidator(spec)
    result = validator.validate(request)

    try:
        result.raise_for_errors()
    except (
            OpenAPIRequestBodyError, OpenAPIMediaTypeError,
            OpenAPISchemaError,
    ):
        return result.parameters
    else:
        return result.parameters
Пример #20
0
    def register() -> None:
        if hupper.is_active():  # pragma: no cover
            hupper.get_reloader().watch_files([filepath])
        spec_dict = read_yaml_file(filepath)

        validate_spec(spec_dict)
        spec = create_spec(spec_dict)

        def spec_view(request: Request) -> FileResponse:
            return FileResponse(filepath,
                                request=request,
                                content_type="text/yaml")

        config.add_route(route_name, route)
        config.add_view(route_name=route_name, view=spec_view)

        custom_formatters = config.registry.settings.get(
            "pyramid_openapi3_formatters")

        config.registry.settings["pyramid_openapi3"] = {
            "filepath": filepath,
            "spec_route_name": route_name,
            "spec": spec,
            "request_validator": RequestValidator(spec, custom_formatters),
            "response_validator": ResponseValidator(spec, custom_formatters),
        }
Пример #21
0
    def register() -> None:
        settings = config.registry.settings.get(apiname)
        if settings and settings.get("spec") is not None:
            raise ConfigurationError(
                "Spec has already been configured. You may only call "
                "pyramid_openapi3_spec or pyramid_openapi3_spec_directory once"
            )

        if hupper.is_active():  # pragma: no cover
            hupper.get_reloader().watch_files([filepath])
        spec_dict = read_yaml_file(filepath)

        validate_spec(spec_dict)
        spec = create_spec(spec_dict)

        def spec_view(request: Request) -> FileResponse:
            return FileResponse(filepath, request=request, content_type="text/yaml")

        config.add_route(route_name, route)
        config.add_view(route_name=route_name, permission=permission, view=spec_view)

        custom_formatters = config.registry.settings.get("pyramid_openapi3_formatters")

        config.registry.settings[apiname] = {
            "filepath": filepath,
            "spec_route_name": route_name,
            "spec": spec,
            "request_validator": RequestValidator(
                spec, custom_formatters=custom_formatters
            ),
            "response_validator": ResponseValidator(
                spec, custom_formatters=custom_formatters
            ),
        }
        APIS.append(apiname)
Пример #22
0
    def check_reload(self) -> None:
        # Because importing yamole (and in turn, yaml) takes
        # significant time, and we only use python-yaml for our API
        # docs, importing it lazily here is a significant optimization
        # to `manage.py` startup.
        #
        # There is a bit of a race here...we may have two processes
        # accessing this module level object and both trying to
        # populate self.data at the same time.  Hopefully this will
        # only cause some extra processing at startup and not data
        # corruption.
        from yamole import YamoleParser

        mtime = os.path.getmtime(self.openapi_path)
        # Using == rather than >= to cover the corner case of users placing an
        # earlier version than the current one
        if self.mtime == mtime:
            return

        with open(self.openapi_path) as f:
            yamole_parser = YamoleParser(f)
        self._openapi = yamole_parser.data
        spec = create_spec(self._openapi)
        self._request_validator = RequestValidator(spec)
        self.create_endpoints_dict()
        self.mtime = mtime
Пример #23
0
    def check_reload(self) -> None:
        # Because importing yaml takes significant time, and we only
        # use python-yaml for our API docs, importing it lazily here
        # is a significant optimization to `manage.py` startup.
        #
        # There is a bit of a race here...we may have two processes
        # accessing this module level object and both trying to
        # populate self.data at the same time.  Hopefully this will
        # only cause some extra processing at startup and not data
        # corruption.

        import yaml
        from jsonref import JsonRef

        with open(self.openapi_path) as f:
            mtime = os.fstat(f.fileno()).st_mtime
            # Using == rather than >= to cover the corner case of users placing an
            # earlier version than the current one
            if self.mtime == mtime:
                return

            openapi = yaml.load(f, Loader=yaml.CSafeLoader)

        spec = create_spec(openapi)
        self._request_validator = RequestValidator(spec)
        self._openapi = naively_merge_allOf_dict(JsonRef.replace_refs(openapi))
        self.create_endpoints_dict()
        self.mtime = mtime
Пример #24
0
def sent_request(client14, container, spec_url='/spec/1.4'):
    version = container['request_data']['headers'].get(
        'X-API-VERSION') or '1.4'
    resp = client14.simulate_get('/spec/{}'.format(version))
    assert HTTP_OK == resp.status
    spec = create_spec(resp.json)
    req = FalconOpenAPIWrapper(app, **container['request_data'])

    validator = RequestValidator(spec)
    result = validator.validate(req)
    assert not result.errors

    validator = ResponseValidator(spec)
    result = validator.validate(req, req)
    assert not result.errors
    container['response'] = req.request
Пример #25
0
def spec_validate_parameters(spec, request, request_factory=None):
    if request_factory is not None:
        request = request_factory(request)

    validator = RequestValidator(spec)
    result = validate_parameters(validator, request)

    return result.parameters
Пример #26
0
def spec_validate_body(spec, request, request_factory=None):
    if request_factory is not None:
        request = request_factory(request)

    validator = RequestValidator(spec)
    result = validate_body(validator, request)

    return result.body
Пример #27
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 == {}
Пример #28
0
    def validate(*args, **kwargs):

        if ENABLE_OPENAPI_VALIDATION:
            spec = get_openapi_spec()
            openapi_request = FlaskOpenAPIRequest(request)
            validator = RequestValidator(spec)
            result = validator.validate(openapi_request)
            result.raise_for_errors()

        response = function(*args, **kwargs)

        if ENABLE_OPENAPI_VALIDATION:
            openapi_response = FlaskOpenAPIResponse(response)
            validator = ResponseValidator(spec)
            result = validator.validate(openapi_request, openapi_response)
            result.raise_for_errors()

        return response
Пример #29
0
def validate_request(response):
    """Validate an API request"""
    path = (Path(here) / '../jupyterlab_server/rest-api.yml').resolve()
    yaml = YAML(typ='safe')
    spec_dict = yaml.load(path.read_text(encoding='utf-8'))
    spec = create_spec(spec_dict)

    validator = RequestValidator(spec)
    request = wrap_request(response.request, spec)
    result = validator.validate(request)
    print(result.errors)
    result.raise_for_errors()

    validator = ResponseValidator(spec)
    response = wrap_response(response)
    result = validator.validate(request, response)
    print(result.errors)
    result.raise_for_errors()
Пример #30
0
    def __init__(self, get_response):
        self.get_response = get_response

        if not hasattr(settings, "OPENAPI_SPEC"):
            raise ImproperlyConfigured("OPENAPI_SPEC not defined in settings")

        request_validator = RequestValidator(settings.OPENAPI_SPEC)
        response_validator = ResponseValidator(settings.OPENAPI_SPEC)
        self.validation_processor = OpenAPIProcessor(request_validator,
                                                     response_validator)
Пример #31
0
def validate_data(path, request, response):
    if response.status_code == status.HTTP_405_METHOD_NOT_ALLOWED:
        return

    spec = _load_spec(resolve(path).kwargs.get('version'))
    request = DRFOpenAPIRequest(request)
    response = DRFOpenAPIResponse(response)

    # request
    validator = RequestValidator(spec, custom_formatters=CUSTOM_FORMATTERS)
    result = validator.validate(request)
    try:
        result.raise_for_errors()
    except OpenAPIMediaTypeError:
        assert response.status_code == status.HTTP_400_BAD_REQUEST
    except OpenAPIParameterError:
        # TODO(stephenfin): In API v2.0, this should be an error. As things
        # stand, we silently ignore these issues.
        assert response.status_code == status.HTTP_200_OK

    # response
    validator = ResponseValidator(spec, custom_formatters=CUSTOM_FORMATTERS)
    result = validator.validate(request, response)
    result.raise_for_errors()