Skip to content

Allow "Required: False" on Response headers - Fix #1261 #1293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions connexion/decorators/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ def validate_response(self, data, status_code, headers, url):
raise NonConformingResponseBody(message=str(e))

if response_definition and response_definition.get("headers"):
response_definition_header_keys = response_definition.get("headers").keys()
header_keys = headers.keys()
missing_keys = response_definition_header_keys - header_keys
required_header_keys = {k for (k, v) in response_definition.get("headers").items()
if v.get("required", False)}
header_keys = set(headers.keys())
missing_keys = required_header_keys - header_keys
if missing_keys:
pretty_list = ', '.join(missing_keys)
msg = ("Keys in header don't match response specification. "
Expand Down
11 changes: 9 additions & 2 deletions tests/api/test_headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ def test_headers_produces(simple_app):
assert response.headers["Location"] == "http://localhost/my/uri"


def test_header_not_returned(simple_app):
app_client = simple_app.app.test_client()
def test_header_not_returned(simple_openapi_app):
app_client = simple_openapi_app.app.test_client()

response = app_client.post('/v1.0/goodday/noheader', data={}) # type: flask.Response
assert response.status_code == 500 # view_func has not returned what was promised in spec
Expand All @@ -42,3 +42,10 @@ def test_no_content_object_and_have_headers(simple_app):
resp = app_client.get('/v1.0/test-204-with-headers-nocontent-obj')
assert resp.status_code == 204
assert 'X-Something' in resp.headers


def test_optional_header(simple_openapi_app):
app_client = simple_openapi_app.app.test_client()
resp = app_client.get('/v1.0/test-optional-headers')
assert resp.status_code == 200
assert 'X-Optional-Header' not in resp.headers
4 changes: 4 additions & 0 deletions tests/fakeapi/hello/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,3 +601,7 @@ def get_date():

def get_uuid():
return {'value': uuid.UUID(hex='e7ff66d0-3ec2-4c4e-bed0-6e4723c24c51')}


def test_optional_headers():
return {}, 200
19 changes: 19 additions & 0 deletions tests/fixtures/simple/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,7 @@ paths:
description: The URI of the created resource
schema:
type: string
required: true
content:
'application/json':
schema:
Expand All @@ -714,6 +715,7 @@ paths:
description: The URI of the created resource
schema:
type: string
required: true
content:
'application/json':
schema:
Expand All @@ -731,6 +733,7 @@ paths:
description: The URI of the created resource
schema:
type: string
required: true
content:
text/plain:
schema:
Expand Down Expand Up @@ -1140,6 +1143,22 @@ paths:
application/json:
schema:
type: object
/test-optional-headers:
get:
operationId: fakeapi.hello.test_optional_headers
responses:
'200':
description: Some object response
content:
application/json:
schema:
type: object
headers:
X-Optional-Header:
description: Optional header
schema:
type: string
required: false

servers:
- url: http://localhost:{port}/{basePath}
Expand Down
15 changes: 0 additions & 15 deletions tests/fixtures/simple/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -556,21 +556,6 @@ paths:
required: true
type: string

/goodday/noheader:
post:
summary: Generate good day greeting
description: Generates a good day message.
operationId: fakeapi.hello.post_goodday_no_header
responses:
201:
description: gooday response
headers:
Location:
type: string
description: The URI of the created resource
schema:
type: object

/goodevening/{name}:
post:
summary: Generate good evening
Expand Down