Beispiel #1
0
def test_request_with_no_json(petstore_spec):
    request = Mock(spec=IncomingRequest, path={'petId': '1234'},
                   json=Mock(side_effect=ValueError("No json here bub")))
    op = petstore_spec.resources['pet'].operations['updatePet']
    with pytest.raises(SwaggerMappingError) as excinfo:
        unmarshal_request(request, op)
    assert "Error reading request body JSON" in str(excinfo.value)
def test_request_with_no_json(petstore_spec):
    request = Mock(spec=IncomingRequest, path={'petId': '1234'},
                   json=Mock(side_effect=ValueError("No json here bub")))
    op = petstore_spec.resources['pet'].operations['updatePet']
    with pytest.raises(SwaggerMappingError) as excinfo:
        unmarshal_request(request, op)
    assert "Error reading request body JSON" in str(excinfo.value)
def test_correct_request_with_apiKey_security(getPetByIdPetstoreOperation):
    request = Mock(
        spec=IncomingRequest,
        path={'petId': '1234'},
        headers={'api-key': 'key1'},
    )
    unmarshal_request(request, getPetByIdPetstoreOperation)
def test_correct_request_with_apiKey_security(petstore_spec):
    request = Mock(
        spec=IncomingRequest,
        path={'petId': '1234'},
        headers={'api_key': 'key1'},
    )
    op = petstore_spec.resources['pet'].operations['getPetById']
    unmarshal_request(request, op)
Beispiel #5
0
def test_correct_request_with_apiKey_security(petstore_spec):
    request = Mock(
        spec=IncomingRequest,
        path={'petId': '1234'},
        headers={'api_key': 'key1'},
    )
    op = petstore_spec.resources['pet'].operations['getPetById']
    unmarshal_request(request, op)
def test_wrong_request_with_apiKey_security(getPetByIdPetstoreOperation):
    request = Mock(
        spec=IncomingRequest,
        path={'petId': '1234'},
        headers={},
    )
    with pytest.raises(SwaggerSecurityValidationError):
        unmarshal_request(request, getPetByIdPetstoreOperation)
def test_wrong_request_with_apiKey_security(petstore_spec):
    request = Mock(
        spec=IncomingRequest,
        path={'petId': '1234'},
        headers={},
    )
    op = petstore_spec.resources['pet'].operations['getPetById']
    with pytest.raises(SwaggerSecurityValidationError):
        unmarshal_request(request, op)
Beispiel #8
0
def test_wrong_request_with_apiKey_security(petstore_spec):
    request = Mock(
        spec=IncomingRequest,
        path={'petId': '1234'},
        headers={},
    )
    op = petstore_spec.resources['pet'].operations['getPetById']
    with pytest.raises(SwaggerSecurityValidationError):
        unmarshal_request(request, op)
Beispiel #9
0
    def process_resource(self, request, response, resource, params):
        # pylint: disable=unused-argument
        bravado_request = _BravadoRequest(request, params)

        get_op = functools.partial(
            self._spec.get_op_for_request,
            path_pattern=request.uri_template,
        )

        operation = get_op(request.method)
        if not operation:
            # The URI exists but the method is wrong.
            # So we are going to reply with an error 405.
            # Error 405 requires we provide the list of allowed methods
            # for this URI. If None is found, then we produce a 404 error.
            allowed = [m for m in falcon.HTTP_METHODS if get_op(m)]
            if allowed:
                raise falcon.HTTPMethodNotAllowed(allowed)
            raise falcon.HTTPNotFound

        try:
            validated = unmarshal_request(bravado_request, operation)
        except ValidationError as e:
            raise _HTTPBadRequest(e)
        else:
            body = validated.pop('body', None)
            if body:
                validated.update(body)
            params.clear()
            params.update(validated)
Beispiel #10
0
 def unmarshal_request(self) -> dict:
     b_req = BravadoRequest(self)
     operation = self.spec.get_op_for_request(request.method.lower(), b_req.endpoint())
     if not operation:
         raise OpenAPIError('Failed to find proper operation method = {}, endpoint = {}'.format(
             request.method.lower(), b_req.endpoint()
         ))
     return unmarshal_request(b_req, operation)
Beispiel #11
0
def test_with_not_string_headers(
    minimal_swagger_dict,
    getPetById_spec,
    request_dict,
    swagger_type,
    swagger_format,
    header_name,
    header_value,
):
    url = '/pet/{petId}'
    parameter = {
        'name': header_name,
        'in': 'header',
        'required': False,
        'type': swagger_type,
    }
    if swagger_format:
        parameter['format'] = swagger_format
    minimal_swagger_dict['paths'][url]['get']['parameters'].append(parameter)

    minimal_swagger_spec = build_swagger_spec(minimal_swagger_dict)
    request_dict['url'] = url

    operation = Operation.from_spec(
        swagger_spec=minimal_swagger_spec,
        path_name='/pet/{petId}',
        http_method='get',
        op_spec=getPetById_spec,
    )

    petId = 34
    api_key = 'foo'
    request = construct_request(
        operation=operation,
        request_options={'headers': {
            header_name: header_value
        }},
        petId=petId,
        api_key=api_key,
    )

    # To unmarshall a request bravado-core needs the request to be wrapped
    # by an object with a specific list of attributes
    request_object = type(
        'IncomingRequest', (IncomingRequest, ), {
            'path': {
                'petId': petId
            },
            'query': {},
            'form': {},
            'headers': request['headers'],
            'files': mock.Mock(),
        })

    assert request['headers'][header_name] == str(header_value)
    unmarshalled_request = unmarshal_request(request_object, operation)
    assert unmarshalled_request[header_name] == header_value
Beispiel #12
0
def test_request_with_path_parameter(getPetByIdPetstoreOperation):
    request = Mock(
        spec=IncomingRequest,
        path={'petId': '1234'},
        headers={'api-key': 'key1'},
    )
    # /pet/{pet_id} fits the bill
    request_data = unmarshal_request(request, getPetByIdPetstoreOperation)
    assert request_data['petId'] == 1234
    assert request_data['api-key'] == 'key1'
Beispiel #13
0
 def validate_request_call(self, op, **kargs):
     params = unmarshal_request(self.request, op)
     response = self.app.request(op.path_name.format_map(params),
                                 body=json.dumps(self.request.json()).encode(),
                                 method=op.http_method.upper(),
                                 headers=self.headers, **kargs)
     schema = self.spec.deref(op.op_spec['responses'][str(response.status_code)])
     casted_resp = self.cast_bravado_response(response)
     validate_response(schema, op, casted_resp)
     return response
Beispiel #14
0
def swaggerize_request(request, op, **kwargs):
    """
    Delegate handling the Swagger concerns of the request to bravado-core.
    Post-invocation, the Swagger request parameters are available as a dict
    named `swagger_data` on the Pyramid request.

    :type request: :class:`pyramid.request.Request`
    :type op: :class:`bravado_core.operation.Operation`
    """
    request_data = unmarshal_request(request, op)
    return request_data
Beispiel #15
0
def swaggerize_request(request, op, **kwargs):
    """
    Delegate handling the Swagger concerns of the request to bravado-core.
    Post-invocation, the Swagger request parameters are available as a dict
    named `swagger_data` on the Pyramid request.

    :type request: :class:`pyramid.request.Request`
    :type op: :class:`bravado_core.operation.Operation`
    """
    request_data = unmarshal_request(request, op)
    return request_data
def test_request_with_path_parameter(petstore_spec):
    request = Mock(
        spec=IncomingRequest,
        path={'petId': '1234'},
        headers={'api_key': 'key1'},
    )
    # /pet/{pet_id} fits the bill
    op = petstore_spec.resources['pet'].operations['getPetById']
    request_data = unmarshal_request(request, op)
    assert request_data['petId'] == 1234
    assert request_data['api_key'] == 'key1'
def test_request_with_path_parameter(petstore_spec):
    request = Mock(
        spec=IncomingRequest,
        path={'petId': '1234'},
        headers={'api_key': 'key1'},
    )
    # /pet/{pet_id} fits the bill
    op = petstore_spec.resources['pet'].operations['getPetById']
    request_data = unmarshal_request(request, op)
    assert request_data['petId'] == 1234
    assert request_data['api_key'] == 'key1'
Beispiel #18
0
def test_only_one_security_definition_in_use_at_time(
    security_spec,
    resource,
    operation,
    query,
    headers,
    expect_to_raise,
):
    request = Mock(
        spec=IncomingRequest,
        headers=headers,
        query=query,
    )

    op = security_spec.resources[resource].operations[operation]
    try:
        with pytest.raises(SwaggerSecurityValidationError):
            unmarshal_request(request, op)
    except:
        if expect_to_raise:
            raise
Beispiel #19
0
def test_with_not_string_headers(
    minimal_swagger_dict, getPetById_spec, request_dict,
    swagger_type, swagger_format, header_name, header_value,
):
    url = '/pet/{petId}'
    parameter = {
        'name': header_name,
        'in': 'header',
        'required': False,
        'type': swagger_type,
    }
    if swagger_format:
        parameter['format'] = swagger_format
    minimal_swagger_dict['paths'][url]['get']['parameters'].append(parameter)

    minimal_swagger_spec = build_swagger_spec(minimal_swagger_dict)
    request_dict['url'] = url

    operation = Operation.from_spec(
        swagger_spec=minimal_swagger_spec,
        path_name='/pet/{petId}',
        http_method='get',
        op_spec=getPetById_spec,
    )

    petId = 34
    api_key = 'foo'
    request = construct_request(
        operation=operation,
        request_options={'headers': {header_name: header_value}},
        petId=petId,
        api_key=api_key,
    )

    # To unmarshall a request bravado-core needs the request to be wrapped
    # by an object with a specific list of attributes
    request_object = type('IncomingRequest', (IncomingRequest,), {
        'path': {'petId': petId},
        'query': {},
        'form': {},
        'headers': request['headers'],
        'files': mock.Mock(),
    })

    expected_header_value = str(header_value)
    # we need to handle a backwards-incompatible change in bravado-core 5.0.5
    if swagger_type == 'boolean':
        assert request['headers'][header_name] in (expected_header_value, expected_header_value.lower())
    else:
        assert request['headers'][header_name] == expected_header_value

    unmarshalled_request = unmarshal_request(request_object, operation)
    assert unmarshalled_request[header_name] == header_value
def test_only_one_security_definition_in_use_at_time(
    security_spec,
    resource,
    operation,
    query,
    headers,
    expect_to_raise,
):
    request = Mock(
        spec=IncomingRequest,
        headers=headers,
        query=query,
    )

    op = security_spec.resources[resource].operations[operation]
    raised_exception = None
    try:
        unmarshal_request(request, op)
    except SwaggerSecurityValidationError as e:
        raised_exception = e

    assert bool(raised_exception is not None) is expect_to_raise
def test_only_one_security_definition_in_use_at_time(
    security_spec,
    resource,
    operation,
    query,
    headers,
    expect_to_raise,
):
    request = Mock(
        spec=IncomingRequest,
        headers=headers,
        query=query,
    )

    op = security_spec.resources[resource].operations[operation]
    raised_exception = None
    try:
        unmarshal_request(request, op)
    except SwaggerSecurityValidationError as e:
        raised_exception = e

    assert bool(raised_exception is not None) is expect_to_raise
Beispiel #22
0
 def validate_request_call(self, op, **kargs):
     params = unmarshal_request(self.request, op)
     response = self.app.request(op.path_name.format_map(params),
                                 body=json.dumps(
                                     self.request.json()).encode(),
                                 method=op.http_method.upper(),
                                 headers=self.headers,
                                 **kargs)
     schema = self.spec.deref(op.op_spec["responses"][str(
         response.status_code)])
     casted_resp = self.cast_bravado_response(response)
     validate_response(schema, op, casted_resp)
     return response
def test_request_with_no_json_and_optional_body_parameter(petstore_spec):
    request = Mock(spec=IncomingRequest,
                   path={'petId': '1234'},
                   json=Mock(side_effect=ValueError("No json here bub")))
    op = petstore_spec.resources['pet'].operations['updatePet']
    op.op_spec['parameters'][0]['required'] = False
    op = Operation.from_spec(
        swagger_spec=petstore_spec,
        path_name=op.path_name,
        http_method=op.http_method,
        op_spec=op.op_spec,
    )
    assert unmarshal_request(request, op) == {'body': None}
Beispiel #24
0
def swaggerize_request(request, op, **kwargs):
    """
    Delegate handling the Swagger concerns of the request to bravado-core.
    Post-invocation, the Swagger request parameters are available as a dict
    named `swagger_data` on the Pyramid request.

    :type request: :class:`pyramid.request.Request`
    :type op: :class:`bravado_core.operation.Operation`
    :raises: RequestValidationError, RequestAuthenticationError
    """
    try:
        request_data = unmarshal_request(request, op)
    except SwaggerSecurityValidationError as e:
        six.raise_from(RequestAuthenticationError(e), e)
    return request_data
Beispiel #25
0
def swaggerize_request(request, op, **kwargs):
    """
    Delegate handling the Swagger concerns of the request to bravado-core.
    Post-invocation, the Swagger request parameters are available as a dict
    named `swagger_data` on the Pyramid request.

    :type request: :class:`pyramid.request.Request`
    :type op: :class:`bravado_core.operation.Operation`
    :raises: RequestValidationError, RequestAuthenticationError
    """
    try:
        request_data = unmarshal_request(request, op)
    except SwaggerSecurityValidationError as e:
        six.raise_from(RequestAuthenticationError(e), e)
    return request_data
Beispiel #26
0
    def process_resource(self, request, response, resource, params):
        bravado_request = _BravadoRequest(request, params)

        operation = self._spec.get_op_for_request(
            request.method.upper(), request.uri_template)
        if not operation:
            raise falcon.HTTPNotFound

        try:
            validated = unmarshal_request(bravado_request, operation)
        except ValidationError as e:
            raise _HTTPBadRequest(e)
        else:
            body = validated.pop('body', None)
            if body:
                validated.update(body)
            params.clear()
            params.update(validated)
Beispiel #27
0
    def validate_request(self, resource: str, operation: str,
                         model: RequestValidationModel):
        """
        Validate a 'request-like' object
        :param resource: API resource pointer
        :param operation: operation on resource
        :param model: model to validate
        :return: None if validation is successful, otherwise an exception will be raised
        """

        spec = self.spec.resources[resource].operations[operation]
        if not spec:
            raise Base422Exception(
                'No validation available',
                reason='A spec was requested but not resolved from API decs')
        try:
            request_data = unmarshal_request(model, spec)
        except (ValidationError, BaseException) as err:
            raise Base422Exception('Validation Failed', str(err))
        return request_data
def test_request_with_no_parameters(petstore_spec):
    request = Mock(spec=IncomingRequest)
    # /user/logout conveniently has no params
    op = petstore_spec.resources['user'].operations['logoutUser']
    request_data = unmarshal_request(request, op)
    assert 0 == len(request_data)
 def _validate_request(swagger_op):
     unmarshal_request(BottleIncomingRequest(request), swagger_op)
def test_request_with_path_parameter(petstore_spec):
    request = Mock(spec=RequestLike, path={'petId': '1234'})
    # /pet/{pet_id} fits the bill
    op = petstore_spec.resources['pet'].operations['getPetById']
    request_data = unmarshal_request(request, op)
    assert request_data['petId'] == 1234
def test_request_with_no_parameters(petstore_spec):
    request = Mock(spec=RequestLike)
    # /user/logout conveniently has no params
    op = petstore_spec.resources['user'].operations['logoutUser']
    request_data = unmarshal_request(request, op)
    assert 0 == len(request_data)
    def handler_wrapper(**path_params):
        log.info("=> INCOMING REQUEST %s %s -> %s" %
                 (endpoint.method, endpoint.path, handler_func.__name__))

        # Get caller's klue-call-id or generate one
        call_id = request.headers.get('KlueCallID', None)
        if not call_id:
            call_id = str(uuid.uuid4())
        stack.top.call_id = call_id

        # Append current server to call path, or start one
        call_path = request.headers.get('KlueCallPath', None)
        if call_path:
            call_path = "%s.%s" % (call_path, api_name)
        else:
            call_path = api_name
        stack.top.call_path = call_path

        if endpoint.param_in_body or endpoint.param_in_query:
            # Turn the flask request into something bravado-core can process...
            try:
                req = FlaskRequestProxy(request, endpoint.param_in_body)
            except BadRequest:
                ee = error_callback(ValidationError("Cannot parse json data: have you set 'Content-Type' to 'application/json'?"))
                return _responsify(api_spec, ee, 400)

            try:
                # Note: unmarshall validates parameters but does not fail
                # if extra unknown parameters are submitted
                parameters = unmarshal_request(req, endpoint.operation)
                # Example of parameters: {'body': RegisterCredentials()}
            except jsonschema.exceptions.ValidationError as e:
                ee = error_callback(ValidationError(str(e)))
                return _responsify(api_spec, ee, 400)

        # Call the endpoint, with proper parameters depending on whether
        # parameters are in body, query or url
        args = []
        kwargs = {}

        if endpoint.param_in_path:
            kwargs = path_params

        if endpoint.param_in_body:
            # Remove the parameters already defined in path_params
            for k in path_params.keys():
                del parameters[k]
            l = list(parameters.values())
            assert len(l) == 1
            args.append(l[0])

        if endpoint.param_in_query:
            kwargs.update(parameters)

        result = handler_func(*args, **kwargs)

        if not result:
            e = error_callback(KlueException("Have nothing to send in response"))
            return _responsify(api_spec, e, 500)

        # Did we get the expected response?
        if endpoint.produces_html:
            if type(result) is not tuple:
                e = error_callback(KlueException("Method %s should return %s but returned %s" %
                                                 (endpoint.handler_server, endpoint.produces, type(result))))
                return _responsify(api_spec, e, 500)

            # Return an html page
            return result

        elif endpoint.produces_json:
            if not hasattr(result, '__module__') or not hasattr(result, '__class__'):
                e = error_callback(KlueException("Method %s did not return a class instance but a %s" %
                                                 (endpoint.handler_server, type(result))))
                return _responsify(api_spec, e, 500)

            # If it's already a flask Response, just pass it through.
            # Errors in particular may be either passed back as flask Responses, or
            # raised as exceptions to be caught and formatted by the error_callback
            result_type = result.__module__ + "." + result.__class__.__name__
            if result_type == 'flask.wrappers.Response':
                return result

            # Otherwise, assume no error occured and make a flask Response out of
            # the result.

            # TODO: check that result is an instance of a model expected as response from this endpoint
            result_json = api_spec.model_to_json(result)

            # Send a Flask Response with code 200 and result_json
            r = jsonify(result_json)
            r.status_code = 200
            return r
Beispiel #33
0
 def _validate_request(swagger_op, ignore_security_definitions=False):
     if ignore_security_definitions:
         swagger_op = SecurityPatchedOperation(swagger_op)
     return unmarshal_request(BottleIncomingRequest(request), swagger_op)
 def _validate_request(swagger_op):
     unmarshal_request(BottleIncomingRequest(request), swagger_op)
Beispiel #35
0
def validate_request(request):
    path = rule_to_path(request.url_rule.rule)
    op = spec.get_op_for_request(request.method, path)
    request = FlaskRequestProxy(request)
    unmarshal_request(request, op)
Beispiel #36
0
    def handler_wrapper(**path_params):
        if os.environ.get('PYM_DEBUG', None) == '1':
            log.debug("PYM_DEBUG: Request headers are: %s" % dict(request.headers))

        # Get caller's pym-call-id or generate one
        call_id = request.headers.get('PymCallID', None)
        if not call_id:
            call_id = str(uuid.uuid4())
        stack.top.call_id = call_id

        # Append current server to call path, or start one
        call_path = request.headers.get('PymCallPath', None)
        if call_path:
            call_path = "%s.%s" % (call_path, api_name)
        else:
            call_path = api_name
        stack.top.call_path = call_path

        if endpoint.param_in_body or endpoint.param_in_query or endpoint.param_in_formdata:
            # Turn the flask request into something bravado-core can process...
            has_data = endpoint.param_in_body or endpoint.param_in_formdata
            try:
                req = FlaskRequestProxy(request, has_data)
            except BadRequest:
                ee = error_callback(ValidationError("Cannot parse json data: have you set 'Content-Type' to 'application/json'?"))
                return _responsify(api_spec, ee, 400)

            try:
                # Note: unmarshall validates parameters but does not fail
                # if extra unknown parameters are submitted
                parameters = unmarshal_request(req, endpoint.operation)
                # Example of parameters: {'body': RegisterCredentials()}
            except jsonschema.exceptions.ValidationError as e:
                ee = error_callback(ValidationError(str(e)))
                return _responsify(api_spec, ee, 400)

        # Call the endpoint, with proper parameters depending on whether
        # parameters are in body, query or url
        args = []
        kwargs = {}

        if endpoint.param_in_path:
            kwargs = path_params

        if endpoint.param_in_body:
            # Remove the parameters already defined in path_params
            for k in list(path_params.keys()):
                del parameters[k]
            lst = list(parameters.values())
            assert len(lst) == 1

            # Now convert the Bravado body object into a pymacaron model
            body = lst[0]
            cls = get_model(body.__class__.__name__)
            body = cls.from_bravado(body)
            args.append(body)

        if endpoint.param_in_query:
            kwargs.update(parameters)

        if endpoint.param_in_formdata:
            for k in list(path_params.keys()):
                del parameters[k]
            kwargs.update(parameters)

        if os.environ.get('PYM_DEBUG', None) == '1':
            log.debug("PYM_DEBUG: Request args are: [args: %s] [kwargs: %s]" % (args, kwargs))

        result = handler_func(*args, **kwargs)

        if not result:
            e = error_callback(PyMacaronCoreException("Have nothing to send in response"))
            return _responsify(api_spec, e, 500)

        # Did we get the expected response?
        if endpoint.produces_html:
            if type(result) is not tuple:
                e = error_callback(PyMacaronCoreException("Method %s should return %s but returned %s" %
                                                          (endpoint.handler_server, endpoint.produces, type(result))))
                return _responsify(api_spec, e, 500)

            # Return an html page
            return result

        elif endpoint.produces_json:
            if not hasattr(result, '__module__') or not hasattr(result, '__class__'):
                e = error_callback(PyMacaronCoreException("Method %s did not return a class instance but a %s" %
                                                          (endpoint.handler_server, type(result))))
                return _responsify(api_spec, e, 500)

            # If it's already a flask Response, just pass it through.
            # Errors in particular may be either passed back as flask Responses, or
            # raised as exceptions to be caught and formatted by the error_callback
            result_type = result.__module__ + "." + result.__class__.__name__
            if result_type == 'flask.wrappers.Response':
                return result

            # We may have got a pymacaron Error instance, in which case
            # it has a http_reply() method...
            if hasattr(result, 'http_reply'):
                # Let's transform this Error into a flask Response
                log.info("Looks like a pymacaron error instance - calling .http_reply()")
                return result.http_reply()

            # Otherwise, assume no error occured and make a flask Response out of
            # the result.

            # TODO: check that result is an instance of a model expected as response from this endpoint
            result_json = api_spec.model_to_json(result)

            # Send a Flask Response with code 200 and result_json
            r = jsonify(result_json)
            r.status_code = 200
            return r