Skip to content
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

Validate accordingly with content-type defined in spec #205

Merged
merged 4 commits into from
Apr 7, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 0 additions & 1 deletion connexion/decorators/produces.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ def wrapper(*args, **kwargs):
logger.debug('Endpoint returned a Flask Response', extra={'url': url, 'mimetype': data.mimetype})
return data

data = str(data)
response = flask.current_app.response_class(data, mimetype=self.mimetype) # type: flask.Response
response = self.process_headers(response, headers)

Expand Down
5 changes: 4 additions & 1 deletion connexion/decorators/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import logging
from ..exceptions import NonConformingResponseBody, NonConformingResponseHeaders
from ..problem import problem
from ..utils import produces_json
from .validation import ResponseBodyValidator
from .decorator import BaseDecorator
from jsonschema import ValidationError
Expand Down Expand Up @@ -48,7 +49,9 @@ def validate_response(self, data, status_code, headers):
response_definition = self.operation.resolve_reference(response_definition)
# TODO handle default response definitions

if response_definition and response_definition.get("schema"):
if response_definition and "schema" in response_definition \
and (produces_json([self.mimetype]) or
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using parenthesis here would look better than using line continuations ('').

self.mimetype == 'text/plain'): # text/plain can also be validated with json schema
schema = response_definition.get("schema")
v = ResponseBodyValidator(schema)
try:
Expand Down
7 changes: 4 additions & 3 deletions connexion/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,16 +264,17 @@ def _retrieve_reference(self, reference):
return definition

def get_mimetype(self):
# if the endpoint as no 'produces' then the default is 'application/json'
default_mimetype = 'application/json'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is a constant you should put it a the module level to avoid creating a string every time get_mimetype is called.

if produces_json(self.produces): # endpoint will return json
try:
return self.produces[0]
except IndexError:
# if the endpoint as no 'produces' then the default is 'application/json'
return 'application/json'
return default_mimetype
elif len(self.produces) == 1:
return self.produces[0]
else:
return None
return default_mimetype

def resolve_parameters(self, parameters):
for param in parameters:
Expand Down
25 changes: 25 additions & 0 deletions tests/api/test_responses.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
from struct import unpack

from connexion.decorators.produces import JSONEncoder

Expand Down Expand Up @@ -127,3 +128,27 @@ def default(self, o):
assert resp.status_code == 200
response = json.loads(resp.data.decode())
assert response['theResult'] == 'cool result'


def test_content_type_not_json(simple_app):
app_client = simple_app.app.test_client()

resp = app_client.get('/v1.0/blob-response')
assert resp.status_code == 200

# validate binary content
text, number = unpack('!4sh', resp.data)
assert text == b'cool'
assert number == 8


def test_maybe_blob_or_json(simple_app):
app_client = simple_app.app.test_client()

resp = app_client.get('/v1.0/binary-response')
assert resp.status_code == 200
assert resp.content_type == 'application/octet-stream'
# validate binary content
text, number = unpack('!4sh', resp.data)
assert text == b'cool'
assert number == 8
10 changes: 8 additions & 2 deletions tests/fakeapi/hello.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#!/usr/bin/env python3

from decimal import Decimal

from connexion import problem, request
from connexion import NoContent
from flask import redirect
Expand Down Expand Up @@ -323,3 +321,11 @@ def test_nullable_param_put(contents):

def test_custom_json_response():
return {'theResult': DummyClass()}, 200


def get_blob_data():
return b'cool\x00\x08'


def get_data_as_binary():
return get_blob_data(), 200, {'Content-Type': 'application/octet-stream'}
24 changes: 24 additions & 0 deletions tests/fixtures/simple/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,30 @@ paths:
type: string
description: the number we wanna test

/blob-response:
get:
operationId: fakeapi.hello.get_blob_data
produces:
- "application/octet-stream"
responses:
200:
description: Some blob response
schema:
type: string
format: binary

/binary-response:
get:
operationId: fakeapi.hello.get_data_as_binary
produces:
- "application/octet-stream"
responses:
200:
description: Everything is ok
schema:
type: string


definitions:
new_stack:
type: object
Expand Down