Пример #1
0
def validate_api_call(schema, raw_request, raw_response):
    """
    Validate the request/response cycle of an api call against a swagger
    schema.  Request/Response objects from the `requests` and `urllib` library
    are supported.
    """
    request = normalize_request(raw_request)
    response = normalize_response(raw_response)

    with ErrorCollection() as errors:
        try:
            validate_request(
                request=request,
                schema=schema,
            )
        except ValidationError as err:
            errors['request'].add_error(err.messages or getattr(err, 'detail'))
            return

        try:
            validate_response(
                response=response,
                request_method=request.method,
                schema=schema,
            )
        except ValidationError as err:
            errors['response'].add_error(err.messages
                                         or getattr(err, 'detail'))
Пример #2
0
def host_validator(value, **kwargs):
    """
    From: http://stackoverflow.com/questions/2532053/validate-a-hostname-string
    According to: http://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names
    """
    scheme, hostname, port, path = decompose_hostname(value)

    if len(hostname) > 255:
        return False
    if hostname[-1] == ".":
        hostname = hostname[:
                            -1]  # strip exactly one dot from the right, if present
    allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)

    with ErrorCollection() as errors:
        if not all(allowed.match(x) for x in hostname.split(".")):
            errors.add_error(
                'invalid',
                MESSAGES['host']['invalid'].format(value),
            )

        if path:
            errors.add_error(
                'path',
                MESSAGES['host']['may_not_include_path'].format(value),
            )

        if scheme:
            errors.add_error(
                'scheme',
                MESSAGES['host']['may_not_include_scheme'].format(value),
            )
Пример #3
0
def validate_operation(request, validators, **kwargs):
    with ErrorCollection() as errors:
        for key, validator in validators.items():
            try:
                validator(request, **kwargs)
            except ValidationError as err:
                errors[key].add_error(err.detail)
Пример #4
0
def validate_parameters(parameter_values, parameters, context):
    validators = construct_multi_parameter_validators(parameters,
                                                      context=context)

    with ErrorCollection() as errors:
        for key, validator in validators.items():
            try:
                validator(parameter_values.get(key, EMPTY))
            except ValidationError as err:
                errors[key].add_error(err.detail)
Пример #5
0
def validate_response(response, request_method, schema):
    """
    Response validation involves the following steps.
       4. validate that the response status_code is in the allowed responses for
          the request method.
       5. validate that the response content validates against any provided
          schemas for the responses.
       6. headers, content-types, etc..., ???
    """
    with ErrorCollection() as errors:
        # 1
        # TODO: tests
        try:
            api_path = validate_path_to_api_path(
                path=response.path,
                **schema
            )
        except ValidationError as err:
            errors['path'].extend(list(err.messages))
            return  # this causes an exception to be raised since errors is no longer falsy.

        path_definition = schema['paths'][api_path] or {}

        # TODO: tests
        try:
            operation_definition = validate_request_method_to_operation(
                request_method=request_method,
                path_definition=path_definition,
            )
        except ValidationError as err:
            errors['method'].append(err.message)
            return

        # 4
        try:
            response_definition = validate_status_code_to_response_definition(
                response=response,
                operation_definition=operation_definition,
            )
        except ValidationError as err:
            errors['status_code'].add_error(err.detail)
        else:
            # 5
            response_validator = generate_response_validator(
                api_path,
                operation_definition=operation_definition,
                path_definition=path_definition,
                response_definition=response_definition,
                context=schema,
            )
            try:
                response_validator(response, context=schema)
            except ValidationError as err:
                errors['body'].add_error(err.detail)
Пример #6
0
def validate_path_items(paths, **kwargs):
    with ErrorCollection() as errors:
        for path, path_definition in paths.items():
            # TODO: move this to its own validation function that validates the keys.
            if not path.startswith('/'):
                errors.add_error(path,
                                 MESSAGES['path']['must_start_with_slash'])

            try:
                path_item_validator(path_definition, **kwargs)
            except ValidationError as err:
                errors.add_error(path, err.detail)
Пример #7
0
def validate_request(request, schema):
    """
    Request validation does the following steps.

       1. validate that the path matches one of the defined paths in the schema.
       2. validate that the request method conforms to a supported methods for the given path.
       3. validate that the request parameters conform to the parameter
          definitions for the operation definition.
    """
    with ErrorCollection() as errors:
        # 1
        try:
            api_path = validate_path_to_api_path(path=request.path,
                                                 context=schema,
                                                 **schema)
        except ValidationError as err:
            errors['path'].add_error(err.detail)
            return  # this causes an exception to be raised since errors is no longer falsy.

        path_definition = schema['paths'][api_path] or {}

        if not path_definition:
            # TODO: is it valid to not have a definition for a path?
            return

        # 2
        try:
            operation_definition = validate_request_method_to_operation(
                request_method=request.method,
                path_definition=path_definition,
            )
        except ValidationError as err:
            errors['method'].add_error(err.detail)
            return

        if operation_definition is None:
            # TODO: is this compliant with swagger, can path operations have a null
            # definition?
            return

        # 3
        operation_validators = construct_operation_validators(
            api_path=api_path,
            path_definition=path_definition,
            operation_definition=operation_definition,
            context=schema,
        )
        try:
            validate_operation(request, operation_validators, context=schema)
        except ValidationError as err:
            errors['method'].add_error(err.detail)
Пример #8
0
def validate_api_request(schema, raw_request):
    request = normalize_request(raw_request)

    with ErrorCollection():
        validate_request(request=request, schema=schema)