Skip to content

Commit

Permalink
Merge pull request #325 from p1c2u/fix/non-required-request-body-fix
Browse files Browse the repository at this point in the history
Non required request body fix
  • Loading branch information
p1c2u committed May 14, 2021
2 parents 3798362 + 4b55054 commit 56450d3
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 12 deletions.
15 changes: 14 additions & 1 deletion openapi_core/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,21 @@ class OpenAPIRequestBodyError(OpenAPIError):
pass


class MissingRequestBodyError(OpenAPIRequestBodyError):
"""Missing request body error"""
pass


@attr.s(hash=True)
class MissingRequestBody(MissingRequestBodyError):
request = attr.ib()

def __str__(self):
return "Missing request body"


@attr.s(hash=True)
class MissingRequestBody(OpenAPIRequestBodyError):
class MissingRequiredRequestBody(MissingRequestBodyError):
request = attr.ib()

def __str__(self):
Expand Down
21 changes: 13 additions & 8 deletions openapi_core/validation/request/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from openapi_core.casting.schemas.exceptions import CastError
from openapi_core.deserializing.exceptions import DeserializeError
from openapi_core.exceptions import (
MissingRequiredParameter, MissingParameter, MissingRequestBody,
MissingRequiredParameter, MissingParameter,
MissingRequiredRequestBody, MissingRequestBody,
)
from openapi_core.security.exceptions import SecurityError
from openapi_core.schema.parameters import get_aslist, get_explode
Expand Down Expand Up @@ -175,15 +176,18 @@ def _get_body(self, request, operation):
return None, []

request_body = operation / 'requestBody'

try:
media_type, mimetype = self._get_media_type(
request_body / 'content', request)
except MediaTypeFinderError as exc:
raw_body = self._get_body_value(request_body, request)
except MissingRequiredRequestBody as exc:
return None, [exc, ]
except MissingRequestBody:
return None, []

try:
raw_body = self._get_body_value(request_body, request)
except MissingRequestBody as exc:
media_type, mimetype = self._get_media_type(
request_body / 'content', request)
except MediaTypeFinderError as exc:
return None, [exc, ]

try:
Expand Down Expand Up @@ -233,8 +237,9 @@ def _get_parameter_value(self, param, request):
return location[param['name']]

def _get_body_value(self, request_body, request):
required = request_body.getkey('required', False)
if not request.body and required:
if not request.body:
if request_body.getkey('required', False):
raise MissingRequiredRequestBody(request)
raise MissingRequestBody(request)
return request.body

Expand Down
28 changes: 28 additions & 0 deletions tests/integration/data/v3.0/petstore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,22 @@ paths:
description: Null response
default:
$ref: "#/components/responses/ErrorResponse"
delete:
summary: Delete tags
operationId: deleteTag
tags:
- tags
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/TagDelete'
responses:
'200':
description: Null response
default:
$ref: "#/components/responses/ErrorResponse"
components:
schemas:
Utctime:
Expand Down Expand Up @@ -335,6 +351,18 @@ components:
name:
type: string
additionalProperties: false
TagDelete:
type: object
x-model: TagDelete
required:
- ids
properties:
ids:
type: array
items:
type: integer
format: int64
additionalProperties: false
TagList:
type: array
items:
Expand Down
36 changes: 36 additions & 0 deletions tests/integration/validation/test_petstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -1230,3 +1230,39 @@ def test_post_tags_created_invalid_type(
assert response_result.data.correlationId == correlationId
assert response_result.data.rootCause == rootCause
assert response_result.data.additionalinfo == additionalinfo

def test_delete_tags_with_requestbody(
self, spec, response_validator):
host_url = 'http://petstore.swagger.io/v1'
path_pattern = '/v1/tags'
ids = [1, 2, 3]
data_json = {
'ids': ids,
}
data = json.dumps(data_json)
request = MockRequest(
host_url, 'DELETE', '/tags',
path_pattern=path_pattern, data=data,
)

parameters = validate_parameters(spec, request)
body = validate_body(spec, request)

assert parameters == RequestParameters()
assert isinstance(body, BaseModel)
assert body.ids == ids

def test_delete_tags_no_requestbody(
self, spec, response_validator):
host_url = 'http://petstore.swagger.io/v1'
path_pattern = '/v1/tags'
request = MockRequest(
host_url, 'DELETE', '/tags',
path_pattern=path_pattern,
)

parameters = validate_parameters(spec, request)
body = validate_body(spec, request)

assert parameters == RequestParameters()
assert body is None
8 changes: 5 additions & 3 deletions tests/integration/validation/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from openapi_core.deserializing.exceptions import DeserializeError
from openapi_core.extensions.models.models import BaseModel
from openapi_core.exceptions import (
MissingRequiredParameter, MissingRequestBody, MissingResponseContent,
MissingRequiredParameter, MissingRequiredRequestBody,
MissingResponseContent,
)
from openapi_core.shortcuts import create_spec
from openapi_core.templating.media_types.exceptions import MediaTypeNotFound
Expand Down Expand Up @@ -154,7 +155,7 @@ def test_missing_body(self, validator):
result = validator.validate(request)

assert len(result.errors) == 1
assert type(result.errors[0]) == MissingRequestBody
assert type(result.errors[0]) == MissingRequiredRequestBody
assert result.body is None
assert result.parameters == RequestParameters(
header={
Expand All @@ -166,6 +167,7 @@ def test_missing_body(self, validator):
)

def test_invalid_content_type(self, validator):
data = "csv,data"
headers = {
'api_key': self.api_key_encoded,
}
Expand All @@ -174,7 +176,7 @@ def test_invalid_content_type(self, validator):
}
request = MockRequest(
'https://development.gigantic-server.com', 'post', '/v1/pets',
path_pattern='/v1/pets', mimetype='text/csv',
path_pattern='/v1/pets', mimetype='text/csv', data=data,
headers=headers, cookies=cookies,
)

Expand Down

0 comments on commit 56450d3

Please sign in to comment.