def swagger_validated_function(*args, **kwargs): converted_uri = request.path # convert /pet/mypetsid to /pet/{petId} for key, value in request.view_args.items(): target = '{{{0}}}'.format(key) converted_uri = converted_uri.replace(str(value), target) # Grab the swagger spec for this specific uri and request type request_spec = spec.get_op_for_request( request.method.lower(), converted_uri) # cycle through the params and check any params that are set or required # by the schema for param in request_spec.params.values(): param_spec = get_param_type_spec(param) # TODO - grab out other request types that we care about param_value = None if param.location == 'formData': param_value = request.form.get(param.name) elif param.location == 'path': param_value = request.view_args.get(param.name) if param_value or param.required: try: validate_schema_object(spec, param_spec, param_value) except Exception as e: abort(400, str(e)) return f(*args, **kwargs)
def unmarshal_response(response, op): """Unmarshal incoming http response into a value based on the response specification. :type response: :class:`bravado_core.response.IncomingResponse` :type op: :class:`bravado_core.operation.Operation` :returns: value where type(value) matches response_spec['schema']['type'] if it exists, None otherwise. """ response_spec = get_response_spec(response.status_code, op) def has_content(response_spec): return 'schema' in response_spec if not has_content(response_spec): return None # TODO: Non-json response contents content_spec = response_spec['schema'] content_value = response.json() if op.swagger_spec.config['validate_responses']: validate_schema_object(op.swagger_spec, content_spec, content_value) return unmarshal_schema_object(op.swagger_spec, content_spec, content_value)
def unmarshal_response(response, op): """Unmarshal incoming http response into a value based on the response specification. :type response: :class:`bravado_core.response.IncomingResponse` :type op: :class:`bravado_core.operation.Operation` :returns: value where type(value) matches response_spec['schema']['type'] if it exists, None otherwise. """ deref = op.swagger_spec.deref response_spec = get_response_spec(response.status_code, op) if 'schema' not in response_spec: # If response spec does not define schema return None content_type = response.headers.get('content-type', '').lower() if content_type.startswith(APP_JSON) or content_type.startswith( APP_MSGPACK): content_spec = deref(response_spec['schema']) if content_type.startswith(APP_JSON): content_value = response.json() else: content_value = msgpack.loads(response.raw_bytes, raw=False) if op.swagger_spec.config['validate_responses']: validate_schema_object(op.swagger_spec, content_spec, content_value) return unmarshal_schema_object(op.swagger_spec, content_spec, content_value) # TODO: Non-json response contents return response.text
def validate_response_body(op, response_spec, response): """Validate an outgoing response's body against the response's Swagger specification. :type op: :class:`bravado_core.operation.Operation` :type response_spec: dict :type response: :class:`bravado_core.response.OutgoingResponse` :raises: SwaggerMappingError """ deref = op.swagger_spec.deref # response that returns nothing in the body response_body_spec = deref(response_spec.get("schema")) if response_body_spec is None: if response.text in EMPTY_BODIES: return raise SwaggerMappingError("Response body should be empty: {0}".format(response.text)) if response.content_type not in op.produces: raise SwaggerMappingError( "Response content-type '{0}' is not supported by the Swagger " "specification's content-types '{1}".format(response.content_type, op.produces) ) if response.content_type == APP_JSON: response_value = response.json() validate_schema_object(op.swagger_spec, response_body_spec, response_value) else: # TODO: Expand content-type support for non-json types raise SwaggerMappingError("Unsupported content-type in response: {0}".format(response.content_type))
def unmarshal_response(response, op): """Unmarshal incoming http response into a value based on the response specification. :type response: :class:`bravado_core.response.IncomingResponse` :type op: :class:`bravado_core.operation.Operation` :returns: value where type(value) matches response_spec['schema']['type'] if it exists, None otherwise. """ deref = op.swagger_spec.deref response_spec = get_response_spec(response.status_code, op) def has_content(response_spec): return "schema" in response_spec if not has_content(response_spec): return None # TODO: Non-json response contents content_spec = deref(response_spec["schema"]) content_value = response.json() if op.swagger_spec.config["validate_responses"]: validate_schema_object(op.swagger_spec, content_spec, content_value) return unmarshal_schema_object(op.swagger_spec, content_spec, content_value)
def unmarshal_response_inner(response, op): """ Unmarshal incoming http response into a value based on the response specification. :type response: :class:`bravado_core.response.IncomingResponse` :type op: :class:`bravado_core.operation.Operation` :returns: value where type(value) matches response_spec['schema']['type'] if it exists, None otherwise. """ deref = op.swagger_spec.deref response_spec = get_response_spec(status_code=response.status_code, op=op) if 'schema' not in response_spec: return None content_type = response.headers.get('content-type', '').lower() if content_type.startswith(APP_JSON) or content_type.startswith(APP_MSGPACK): content_spec = deref(response_spec['schema']) if content_type.startswith(APP_JSON): content_value = response.json() else: content_value = unpackb(response.raw_bytes, encoding='utf-8') if op.swagger_spec.config.get('validate_responses', False): validate_schema_object(op.swagger_spec, content_spec, content_value) return unmarshal_schema_object( swagger_spec=op.swagger_spec, schema_object_spec=content_spec, value=content_value, ) # TODO: Non-json response contents return response.text
def unmarshal_param(param, request): """Unmarshal the given parameter from the passed in request like object. :type param: :class:`bravado_core.param.Param` :type request: :class:`bravado_core.request.IncomingRequest` :return: value of parameter """ swagger_spec = param.swagger_spec deref = swagger_spec.deref param_spec = deref(get_param_type_spec(param)) location = param.location param_type = deref(param_spec.get('type')) cast_param = partial(cast_request_param, param_type, param.name) default_value = schema.get_default(swagger_spec, param_spec) if location == 'path': raw_value = cast_param(request.path.get(param.name, None)) elif location == 'query': raw_value = cast_param(request.query.get(param.name, default_value)) elif location == 'header': raw_value = cast_param(request.headers.get(param.name, default_value)) elif location == 'formData': if param_type == 'file': raw_value = request.files.get(param.name, None) else: raw_value = cast_param(request.form.get(param.name, default_value)) elif location == 'body': try: # TODO: verify content-type header raw_value = request.json() except ValueError as json_error: # If the body parameter is required then we should make sure that an exception # is thrown, instead if the body parameter is optional is OK-ish to assume that # raw_value is the default_value if param.required: raise SwaggerMappingError( "Error reading request body JSON: {0}".format(str(json_error)), ) else: raw_value = default_value else: raise SwaggerMappingError( "Don't know how to unmarshal_param with location {0}".format(location), ) if raw_value is None and not param.required: return None if param_type == 'array' and location != 'body': raw_value = unmarshal_collection_format( swagger_spec, param_spec, raw_value, ) if swagger_spec.config['validate_requests']: validate_schema_object(swagger_spec, param_spec, raw_value) value = unmarshal_schema_object(swagger_spec, param_spec, raw_value) return value
def validate_response_headers(op, response_spec, response): """Validate an outgoing response's headers against the response's Swagger specification. :type op: :class:`bravado_core.operation.Operation` :type response_spec: dict :type response: :class:`bravado_core.response.OutgoingResponse` """ deref = op.swagger_spec.deref headers_spec = deref(response_spec.get('headers')) if not headers_spec: return for header_name, header_spec in iteritems(headers_spec): header_spec = deref(header_spec) try: validate_schema_object( op.swagger_spec, header_spec, response.headers.get(header_name), ) except ValidationError as e: e.message = "{0} for header '{1}'".format(e.message, header_name) raise e
def validate_response_body(op, response_spec, response): """ Validate an outgoing response's body against the response's Swagger specification. :type op: :class:`bravado_core.operation.Operation` :type response_spec: dict :type response: :class:`bravado_core.response.OutgoingResponse` :raises: SwaggerMappingError """ # response that returns nothing in the body response_body_spec = response_spec.get('schema') if response_body_spec is None: if response.text in EMPTY_BODIES: return raise SwaggerMappingError("Response body should be empty: {0}".format( response.text)) if response.content_type not in op.produces: raise SwaggerMappingError( "Response content-type '{0}' is not supported by the Swagger " "specification's content-types '{1}".format( response.content_type, op.produces)) if response.content_type == APP_JSON: response_value = response.json() validate_schema_object(op.swagger_spec, response_body_spec, response_value) else: # TODO: Expand content-type support for non-json types raise SwaggerMappingError( "Unsupported content-type in response: {0}".format( response.content_type))
def test_unmarshal_with_object_default(empty_swagger_spec, nullable, required): """With a value set, validation should always pass: (2), (5), (8), (11)""" content_spec = content_spec_factory(required, nullable) value = {'x': 'y'} validate_schema_object(empty_swagger_spec, content_spec, value) result = unmarshal_schema_object(empty_swagger_spec, content_spec, value) assert result == value
def test_allOf_with_ref(composition_spec): pongclone_spec = composition_spec.spec_dict['definitions']['pongClone'] value = { 'additionalFeature': 'Badges', 'gameSystem': 'NES', 'pang': 'value', 'releaseDate': 'October', } validate_schema_object(composition_spec, pongclone_spec, value)
def test_unmarshal_with_primitive_pass(empty_swagger_spec, value, nullable): """Test scenarios in which validation should pass: (1), (3), (4)""" content_spec = { 'type': 'string', 'x-nullable': nullable, } validate_schema_object(empty_swagger_spec, content_spec, value) result = unmarshal_schema_object(empty_swagger_spec, content_spec, value) assert result == value
def marshal_param(param, value, request): """Given an operation's parameter and its value, marshal the value and place it in the proper request destination. Destination is one of: - path - can accept primitive and array of primitive types - query - can accept primitive and array of primitive types - header - can accept primitive and array of primitive types - body - can accept any type - formData - can accept primitive and array of primitive types :type param: :class:`bravado_core.param.Param` :param value: The value to assign to the parameter :type request: dict """ swagger_spec = param.swagger_spec deref = swagger_spec.deref param_spec = deref(get_param_type_spec(param)) location = param.location # Rely on unmarshalling behavior on the other side of the pipe to use # the default value if one is available. if value is None and not param.required: return value = marshal_schema_object(swagger_spec, param_spec, value) if swagger_spec.config['validate_requests']: validate_schema_object(swagger_spec, param_spec, value) param_type = param_spec.get('type') if param_type == 'array' and location != 'body': value = marshal_collection_format(swagger_spec, param_spec, value) encode_param = partial(encode_request_param, param_type, param.name) if location == 'path': token = u'{%s}' % param.name quoted_value = quote(six.text_type(value).encode('utf8'), safe=',') request['url'] = request['url'].replace(token, quoted_value) elif location == 'query': request['params'][param.name] = encode_param(value) elif location == 'header': request['headers'][param.name] = encode_param(value) elif location == 'formData': if param_type == 'file': add_file(param, value, request) else: request.setdefault('data', {})[param.name] = value elif location == 'body': request['headers']['Content-Type'] = APP_JSON request['data'] = json.dumps(value) else: raise SwaggerMappingError( "Don't know how to marshal_param with location {0}". format(location))
def test_unmarshal_with_object_no_req_no_value(empty_swagger_spec, nullable): """When the value is not required and not set at all, validation should pass: (1), (7) """ content_spec = content_spec_factory(False, nullable=nullable) value = {} validate_schema_object(empty_swagger_spec, content_spec, value) result = unmarshal_schema_object(empty_swagger_spec, content_spec, value) assert result == {'x': None} # Missing parameters are re-introduced
def test_unmarshal_with_object_null_value_none(empty_swagger_spec, required): """When nullable is `True` and the value is set to `None`, validation should pass: (9), (12) """ content_spec = content_spec_factory(required, True) value = {'x': None} validate_schema_object(empty_swagger_spec, content_spec, value) result = unmarshal_schema_object(empty_swagger_spec, content_spec, value) assert result == {'x': None}
def marshal_param(param, value, request): """Given an operation's parameter and its value, marshal the value and place it in the proper request destination. Destination is one of: - path - can accept primitive and array of primitive types - query - can accept primitive and array of primitive types - header - can accept primitive and array of primitive types - body - can accept any type - formData - can accept primitive and array of primitive types :type param: :class:`bravado_core.param.Param` :param value: The value to assign to the parameter :type request: dict """ swagger_spec = param.swagger_spec deref = swagger_spec.deref param_spec = deref(get_param_type_spec(param)) location = param.location # Rely on unmarshalling behavior on the other side of the pipe to use # the default value if one is availabe. if value is None and not schema.is_required(swagger_spec, param_spec): return value = marshal_schema_object(swagger_spec, param_spec, value) if swagger_spec.config['validate_requests']: validate_schema_object(swagger_spec, param_spec, value) param_type = param_spec.get('type') if param_type == 'array' and location != 'body': value = marshal_collection_format(swagger_spec, param_spec, value) if location == 'path': token = u'{%s}' % param.name # Don't do any escaping/encoding - http_client will take care of it request['url'] = request['url'].replace(token, six.text_type(value)) elif location == 'query': request['params'][param.name] = value elif location == 'header': request['headers'][param.name] = value elif location == 'formData': if param_type == 'file': add_file(param, value, request) else: request.setdefault('data', {})[param.name] = value elif location == 'body': request['headers']['Content-Type'] = APP_JSON request['data'] = json.dumps(value) else: raise SwaggerMappingError( "Don't know how to marshal_param with location {0}". format(location))
def test_unmarshal_with_object_req_no_value(empty_swagger_spec, nullable): """When the value is required but not set at all, validation should fail: (4), (10) """ content_spec = content_spec_factory(True, nullable) value = {} with pytest.raises(ValidationError) as excinfo: validate_schema_object(empty_swagger_spec, content_spec, value) unmarshal_schema_object(empty_swagger_spec, content_spec, value) assert excinfo.value.message == "'x' is a required property"
def test_unmarshal_with_object_no_null_value_none(empty_swagger_spec, required): """When nullable is `False` and the value is set to `None`, validation should fail: (3), (6) """ content_spec = content_spec_factory(required, False) value = {'x': None} with pytest.raises(ValidationError) as excinfo: validate_schema_object(empty_swagger_spec, content_spec, value) unmarshal_schema_object(empty_swagger_spec, content_spec, value) assert excinfo.value.message == "None is not of type 'string'"
def test_unmarshal_with_primitive_fail(empty_swagger_spec): """Test scenarios in which validation should fail: (2)""" content_spec = { 'type': 'string', 'x-nullable': False, } value = None with pytest.raises(ValidationError) as excinfo: validate_schema_object(empty_swagger_spec, content_spec, value) unmarshal_schema_object(empty_swagger_spec, content_spec, value) assert excinfo.value.message == "None is not of type 'string'"
def unmarshal_response_inner( response, # type: IncomingResponse op, # type: Operation ): # type: (...) -> typing.Optional[T] """ Unmarshal incoming http response into a value based on the response specification. :type response: :class:`bravado_core.response.IncomingResponse` :type op: :class:`bravado_core.operation.Operation` :returns: value where type(value) matches response_spec['schema']['type'] if it exists, None otherwise. """ content_type = response.headers.get('content-type', '').lower() if content_type.startswith(APP_JSON) or content_type.startswith(APP_MSGPACK): use_models = op.swagger_spec.config.get('use_models', True) if content_type.startswith(APP_JSON): content_value = response.json() else: content_value = unpackb(response.raw_bytes) try: response_spec = get_response_spec( status_code=response.status_code, op=op) except MatchingResponseNotFound: if not use_models: return content_value six.reraise(*sys.exc_info()) if 'schema' not in response_spec: if not use_models: return content_value return None content_spec = op.swagger_spec.deref(response_spec['schema']) if op.swagger_spec.config.get('validate_responses', False): validate_schema_object(op.swagger_spec, content_spec, content_value) return unmarshal_schema_object( swagger_spec=op.swagger_spec, schema_object_spec=content_spec, value=content_value, ) if content_type.startswith('application'): return response.raw_bytes # TODO: Non-json response contents return response.text
async def unmarshal_param(param, request): """Unmarshal the given parameter from the passed in request like object. :type param: :class:`bravado_core.param.Param` :type request: :class:`bravado_core.request.IncomingRequest` :return: value of parameter """ swagger_spec = param.swagger_spec deref = swagger_spec.deref param_spec = deref(get_param_type_spec(param)) location = param.location param_type = deref(param_spec.get('type')) cast_param = partial(cast_request_param, param_type, param.name) default_value = schema.get_default(swagger_spec, param_spec) if location == Location.path: raw_value = cast_param(request.match_info.get(param.name, None)) elif location == Location.query: raw_value = cast_param(request.query.get(param.name, default_value)) elif location == Location.header: raw_value = cast_param(request.headers.get(param.name, default_value)) elif location == Location.form_data: if param_type == 'file': raw_value = request.files.get(param.name, None) else: raw_value = cast_param(request.form.get(param.name, default_value)) elif location == Location.body: # TODO: verify content-type header try: raw_value = request.json() except ValueError as json_error: raise SwaggerMappingError( "Error reading request body JSON: {0}".format(str(json_error))) else: raise SwaggerMappingError( "Don't know how to unmarshal_param with location {0}".format( location)) if raw_value is None and not schema.is_required(swagger_spec, param_spec): return None if param_type == 'array' and location != Location.body: raw_value = unmarshal_collection_format(swagger_spec, param_spec, raw_value) if swagger_spec.config['validate_requests']: validate_schema_object(swagger_spec, param_spec, raw_value) value = unmarshal_schema_object(swagger_spec, param_spec, raw_value) return value
def unmarshal_param(param, request): """Unmarshal the given parameter from the passed in request like object. :type param: :class:`bravado_core.param.Param` :type request: :class:`bravado_core.request.IncomingRequest` :return: value of parameter """ swagger_spec = param.swagger_spec deref = swagger_spec.deref param_spec = deref(get_param_type_spec(param)) location = param.location param_type = deref(param_spec.get('type')) cast_param = partial(cast_request_param, param_type, param.name) default_value = schema.get_default(swagger_spec, param_spec) if location == 'path': raw_value = cast_param(request.path.get(param.name, None)) elif location == 'query': raw_value = cast_param(request.query.get(param.name, default_value)) elif location == 'header': raw_value = cast_param(request.headers.get(param.name, default_value)) elif location == 'formData': if param_type == 'file': raw_value = request.files.get(param.name, None) else: raw_value = cast_param(request.form.get(param.name, default_value)) elif location == 'body': # TODO: verify content-type header try: raw_value = request.json() except ValueError as json_error: raise SwaggerMappingError("Error reading request body JSON: {0}". format(str(json_error))) else: raise SwaggerMappingError( "Don't know how to unmarshal_param with location {0}". format(location)) if raw_value is None and not schema.is_required(swagger_spec, param_spec): return None if param_type == 'array' and location != 'body': raw_value = unmarshal_collection_format(swagger_spec, param_spec, raw_value) if swagger_spec.config['validate_requests']: validate_schema_object(swagger_spec, param_spec, raw_value) value = unmarshal_schema_object(swagger_spec, param_spec, raw_value) return value
def validate_response_headers(response_spec, response): """ Validate an outgoing response's headers against the response's Swagger specification. :type response_spec: dict :type response: :class: `bravado_core.response.OutgoingResponse` """ headers_spec = response_spec.get('headers') if not headers_spec: return for header_name, header_spec in headers_spec.iteritems(): validate_schema_object(header_spec, response.headers.get(header_name))
def marshal_param(param, value, request): """Given an operation's parameter and its value, marshal the value and place it in the proper request destination. Destination is one of: - path - can accept primitive and array of primitive types - query - can accept primitive and array of primitive types - header - can accept primitive and array of primitive types - body - can accept any type - formData - can accept primitive and array of primitive types :type param: :class:`bravado_core.param.Param` :param value: The value to assign to the parameter :type request: dict """ swagger_spec = param.swagger_spec deref = swagger_spec.deref spec = deref(get_param_type_spec(param)) location = param.location value = marshal_schema_object(swagger_spec, spec, value) if swagger_spec.config['validate_requests']: validate_schema_object(swagger_spec, spec, value) param_type = spec.get('type') if param_type == 'array' and location != 'body': value = marshal_collection_format(swagger_spec, spec, value) if location == 'path': token = u'{%s}' % param.name # Don't do any escaping/encoding - http_client will take care of it request['url'] = request['url'].replace(token, six.text_type(value)) elif location == 'query': request['params'][param.name] = value elif location == 'header': request['headers'][param.name] = value elif location == 'formData': if param_type == 'file': add_file(param, value, request) else: request.setdefault('data', {})[param.name] = value elif location == 'body': request['headers']['Content-Type'] = APP_JSON request['data'] = json.dumps(value) else: raise SwaggerMappingError( "Don't know how to marshal_param with location {0}". format(location))
def validate_response_headers(op, response_spec, response): """ Validate an outgoing response's headers against the response's Swagger specification. :type op: :class:`bravado_core.operation.Operation` :type response_spec: dict :type response: :class:`bravado_core.response.OutgoingResponse` """ headers_spec = response_spec.get('headers') if not headers_spec: return for header_name, header_spec in iteritems(headers_spec): validate_schema_object(op.swagger_spec, header_spec, response.headers.get(header_name))
def parse_and_validate_parameters(raw_params): initialize_specification() clean_params = {} for parameter in _parsed_spec.spec_dict['parameters']: parameter_spec = _parsed_spec.spec_dict['parameters'][parameter] parameter_type = parameter_spec['type'] parameter_name = parameter_spec['name'] try: value = param.cast_request_param(parameter_type, parameter, raw_params.get(parameter_name)) validate.validate_schema_object(_parsed_spec, parameter_spec, value) clean_params[parameter] = marshal.marshal_schema_object(_parsed_spec, parameter_spec, value) except Exception as e: raise ValueError(e) return clean_params
def validate(self, model_name, object): """Validate an object against its swagger model""" if model_name not in self.swagger_dict['definitions']: raise ValidationError("Swagger spec has no definition for model %s" % model_name) model_def = self.swagger_dict['definitions'][model_name] log.debug("Validating %s" % model_name) return validate_schema_object(self.spec, model_def, object)
def validate_response_body(op, response_spec, response): """Validate an outgoing response's body against the response's Swagger specification. :type op: :class:`bravado_core.operation.Operation` :type response_spec: dict :type response: :class:`bravado_core.response.OutgoingResponse` :raises: SwaggerMappingError """ deref = op.swagger_spec.deref # response that returns nothing in the body response_body_spec = deref(response_spec.get('schema')) if response_body_spec is None: if response.text in EMPTY_BODIES: return raise SwaggerMappingError( "Response body should be empty: {0}".format(response.text), ) if response.content_type not in op.produces: raise SwaggerMappingError( "Response content-type '{0}' is not supported by the Swagger " "specification's content-types '{1}".format( response.content_type, op.produces, ), ) if response.content_type == APP_JSON or response.content_type == APP_MSGPACK: if response.content_type == APP_JSON: response_value = response.json() else: response_value = msgpack.loads(response.raw_bytes, raw=False) validate_schema_object( op.swagger_spec, response_body_spec, response_value, ) elif response.content_type.startswith("text/"): # TODO: support some kind of validation for text/* responses # TODO: but in the meantime don't raise errors for them pass else: # TODO: Expand content-type support for non-json types raise SwaggerMappingError( "Unsupported content-type in response: {0}".format( response.content_type), )
def marshal_param(param, value, request): """ Given an operation parameter and its value, marshal the value and place it in the proper request destination. Destination is one of: - path - can accept primitive and array of primitive types - query - can accept primitive and array of primitive types - header - can accept primitive and array of primitive types - body - can accept any type - formData - can accept primitive and array of primitive types :type param: :class:`bravado_core.param.Param` :param value: The value to assign to the parameter :type request: dict """ spec = get_param_type_spec(param) location = param.location value = marshal_schema_object(param.swagger_spec, spec, value) if param.swagger_spec.config['validate_requests']: validate_schema_object(spec, value) if spec['type'] == 'array' and location != 'body': value = marshal_collection_format(spec, value) if location == 'path': token = u'{%s}' % param.name request['url'] = \ request['url'].replace(token, urllib.quote(unicode(value))) elif location == 'query': request['params'][param.name] = value elif location == 'header': request['headers'][param.name] = value elif location == 'formData': if spec['type'] == 'file': add_file(param, value, request) else: request.setdefault('data', {})[param.name] = value elif location == 'body': request['headers']['Content-Type'] = APP_JSON request['data'] = json.dumps(value) else: raise SwaggerMappingError( "Don't know how to marshal_param with location {0}". format(location))
def validate_response_headers(op, response_spec, response): """Validate an outgoing response's headers against the response's Swagger specification. :type op: :class:`bravado_core.operation.Operation` :type response_spec: dict :type response: :class:`bravado_core.response.OutgoingResponse` """ deref = op.swagger_spec.deref headers_spec = deref(response_spec.get("headers")) if not headers_spec: return for header_name, header_spec in iteritems(headers_spec): header_spec = deref(header_spec) validate_schema_object(op.swagger_spec, header_spec, response.headers.get(header_name))
def validate_response_dict(rule, response_dict, http_method='GET', status_code=200, headers=None): path = rule_to_path(rule) if not headers: headers = {} # TODO: Validate the entire response, including headers # response = Response(response_dict, headers) op = spec.get_op_for_request(http_method, path) response_spec = get_response_spec(status_code, op) # No schema defined? Nothing to validate. if 'schema' not in response_spec: return validate_schema_object(spec, response_spec['schema'], response_dict)
def unmarshal_param(param, request): """Unmarshal the given parameter from the passed in request like object. :type param: :class:`bravado_core.param.Param` :type request: :class:`bravado_core.request.IncomingRequest` :return: value of parameter """ swagger_spec = param.swagger_spec deref = swagger_spec.deref param_spec = deref(get_param_type_spec(param)) location = param.location param_type = deref(param_spec.get('type')) cast_param = partial(cast_request_param, param_type, param.name) default_value = schema.get_default(swagger_spec, param_spec) if location == 'path': raw_value = cast_param(request.path.get(param.name, None)) elif location == 'query': raw_value = cast_param(request.query.get(param.name, default_value)) elif location == 'header': raw_value = cast_param(request.headers.get(param.name, default_value)) elif location == 'formData': if param_type == 'file': raw_value = request.files.get(param.name, None) else: raw_value = cast_param(request.form.get(param.name, default_value)) elif location == 'body': # TODO: verify content-type header raw_value = request.json() else: raise SwaggerMappingError( "Don't know how to unmarshal_param with location {0}".format( location)) if param_type == 'array' and location != 'body': raw_value = unmarshal_collection_format(swagger_spec, param_spec, raw_value) if swagger_spec.config['validate_requests']: validate_schema_object(swagger_spec, param_spec, raw_value) value = unmarshal_schema_object(swagger_spec, param_spec, raw_value) return value
def validate_response_body(op, response_spec, response): """Validate an outgoing response's body against the response's Swagger specification. :type op: :class:`bravado_core.operation.Operation` :type response_spec: dict :type response: :class:`bravado_core.response.OutgoingResponse` :raises: SwaggerMappingError """ deref = op.swagger_spec.deref # response that returns nothing in the body response_body_spec = deref(response_spec.get('schema')) if response_body_spec is None: if response.text in EMPTY_BODIES: return raise SwaggerMappingError( "Response body should be empty: {0}".format(response.text)) if response.content_type not in op.produces: raise SwaggerMappingError( "Response content-type '{0}' is not supported by the Swagger " "specification's content-types '{1}" .format(response.content_type, op.produces)) if response.content_type == APP_JSON or response.content_type == APP_MSGPACK: if response.content_type == APP_JSON: response_value = response.json() else: response_value = msgpack.loads(response.raw_bytes, encoding='utf-8') validate_schema_object( op.swagger_spec, response_body_spec, response_value) elif response.content_type.startswith("text/"): # TODO: support some kind of validation for text/* responses # TODO: but in the meantime don't raise errors for them pass else: # TODO: Expand content-type support for non-json types raise SwaggerMappingError( "Unsupported content-type in response: {0}" .format(response.content_type))
def unmarshal_response_inner( response, # type: IncomingResponse op, # type: Operation ): # type: (...) -> typing.Optional[T] """ Unmarshal incoming http response into a value based on the response specification. :type response: :class:`bravado_core.response.IncomingResponse` :type op: :class:`bravado_core.operation.Operation` :returns: value where type(value) matches response_spec['schema']['type'] if it exists, None otherwise. """ deref = op.swagger_spec.deref response_spec = get_response_spec(status_code=response.status_code, op=op) if 'schema' not in response_spec: return None content_type = response.headers.get('content-type', '').lower() if content_type.startswith(APP_JSON) or content_type.startswith( APP_MSGPACK): content_spec = deref(response_spec['schema']) if content_type.startswith(APP_JSON): content_value = response.json() else: content_value = unpackb(response.raw_bytes, encoding='utf-8') if op.swagger_spec.config.get('validate_responses', False): validate_schema_object(op.swagger_spec, content_spec, content_value) return unmarshal_schema_object( swagger_spec=op.swagger_spec, schema_object_spec=content_spec, value=content_value, ) # TODO: Non-json response contents return response.text
def unmarshal_param(param, request): """Unmarshal the given parameter from the passed in request like object. :type param: :class:`bravado_core.param.Param` :type request: :class:`bravado_core.request.IncomingRequest` """ param_spec = get_param_type_spec(param) location = param.location cast_param = partial(cast_request_param, param_spec['type'], param.name) default_value = schema.get_default(param_spec) if location == 'path': raw_value = cast_param(request.path.get(param.name, None)) elif location == 'query': raw_value = cast_param(request.query.get(param.name, default_value)) elif location == 'header': raw_value = cast_param(request.headers.get(param.name, default_value)) elif location == 'formData': if param_spec['type'] == 'file': raw_value = request.files.get(param.name, None) else: raw_value = cast_param(request.form.get(param.name, default_value)) elif location == 'body': # TODO: verify content-type header raw_value = request.json() else: raise SwaggerMappingError( "Don't know how to unmarshal_param with location {0}". format(location)) if param_spec['type'] == 'array' and location != 'body': raw_value = unmarshal_collection_format(param_spec, raw_value) if param.swagger_spec.config['validate_requests']: validate_schema_object(param.swagger_spec, param_spec, raw_value) value = unmarshal_schema_object(param.swagger_spec, param_spec, raw_value) return value
def test_no_validation_when_no_type(minimal_swagger_spec): validate_schema_object(minimal_swagger_spec, {}, None)
from bravado_core.validate import validate_schema_object from jsonschema import ValidationError from six.moves.urllib.parse import urljoin from six.moves.urllib.request import pathname2url old_client = SwaggerClient.from_url(spec_url=urljoin( 'file:', pathname2url(abspath('old.yaml'))), ) new_client = SwaggerClient.from_url(spec_url=urljoin( 'file:', pathname2url(abspath('new.yaml'))), ) object_to_validate = {'property': 'True'} print('Validating the get endpoint response with old client: Succeeded') validate_schema_object( swagger_spec=old_client.swagger_spec, schema_object_spec=old_client.swagger_spec. definitions['get_endpoint_response']._model_spec, value=object_to_validate, ) print('Validating the get endpoint response with the new client: Failed') try: validate_schema_object( swagger_spec=new_client.swagger_spec, schema_object_spec=new_client.swagger_spec. definitions['get_endpoint_response']._model_spec, value=object_to_validate, ) raise RuntimeError('An error was expected') except ValidationError: pass
def test_unknown_type(minimal_swagger_spec): with pytest.raises(SwaggerMappingError) as excinfo: validate_schema_object(minimal_swagger_spec, {'type': 'unknown'}, 'foo') assert 'Unknown type' in str(excinfo.value)