mirror of
https://github.com/sprockets/sprockets.mixins.http.git
synced 2024-11-14 19:29:31 +00:00
Merge pull request #41 from nvllsvm/suffix
Add support for content-type suffixes
This commit is contained in:
commit
e0e67363a8
2 changed files with 80 additions and 27 deletions
|
@ -20,6 +20,8 @@ LOGGER = logging.getLogger(__name__)
|
|||
|
||||
CONTENT_TYPE_JSON = headers.parse_content_type('application/json')
|
||||
CONTENT_TYPE_MSGPACK = headers.parse_content_type('application/msgpack')
|
||||
CONTENT_TYPE_SUFFIX_JSON = 'json'
|
||||
CONTENT_TYPE_SUFFIX_MSGPACK = 'msgpack'
|
||||
AVAILABLE_CONTENT_TYPES = [CONTENT_TYPE_JSON, CONTENT_TYPE_MSGPACK]
|
||||
DEFAULT_USER_AGENT = 'sprockets.mixins.http/{}'.format(__version__)
|
||||
|
||||
|
@ -206,24 +208,30 @@ class HTTPResponse:
|
|||
:rtype: mixed
|
||||
|
||||
"""
|
||||
if not self._responses or not self._responses[-1].body:
|
||||
return None
|
||||
if 'Content-Type' not in self._responses[-1].headers:
|
||||
return self._responses[-1].body
|
||||
try:
|
||||
content_type = algorithms.select_content_type([
|
||||
headers.parse_content_type(
|
||||
self._responses[-1].headers['Content-Type'])
|
||||
], AVAILABLE_CONTENT_TYPES)
|
||||
except errors.NoMatch:
|
||||
return self._responses[-1].body
|
||||
if not self._responses:
|
||||
return
|
||||
response = self._responses[-1]
|
||||
if not response.body:
|
||||
return
|
||||
if 'Content-Type' not in response.headers:
|
||||
return response.body
|
||||
|
||||
if content_type[0] == CONTENT_TYPE_JSON:
|
||||
return self._decode(
|
||||
self._json.loads(self._decode(self._responses[-1].body)))
|
||||
elif content_type[0] == CONTENT_TYPE_MSGPACK: # pragma: nocover
|
||||
return self._decode(self._msgpack.unpackb(
|
||||
self._responses[-1].body))
|
||||
content_type = headers.parse_content_type(
|
||||
response.headers['Content-Type'])
|
||||
if content_type.content_suffix == CONTENT_TYPE_SUFFIX_JSON:
|
||||
return self._decode(self._json.loads(self._decode(response.body)))
|
||||
elif content_type.content_suffix == CONTENT_TYPE_SUFFIX_MSGPACK:
|
||||
return self._decode(self._msgpack.unpackb(response.body))
|
||||
|
||||
try:
|
||||
selected = algorithms.select_content_type(
|
||||
[content_type], AVAILABLE_CONTENT_TYPES)
|
||||
except errors.NoMatch:
|
||||
return response.body
|
||||
if selected[0] == CONTENT_TYPE_JSON:
|
||||
return self._decode(self._json.loads(self._decode(response.body)))
|
||||
elif selected[0] == CONTENT_TYPE_MSGPACK:
|
||||
return self._decode(self._msgpack.unpackb(response.body))
|
||||
|
||||
def _error_message(self):
|
||||
"""Try and extract the error message from a HTTP error response.
|
||||
|
@ -466,9 +474,11 @@ class HTTPClientMixin:
|
|||
if body is None or not isinstance(body, (dict, list)):
|
||||
return body
|
||||
content_type = headers.parse_content_type(content_type)
|
||||
if content_type == CONTENT_TYPE_JSON:
|
||||
if content_type == CONTENT_TYPE_JSON \
|
||||
or content_type.content_suffix == CONTENT_TYPE_SUFFIX_JSON:
|
||||
return self.__hcm_json.dumps(body)
|
||||
elif content_type == CONTENT_TYPE_MSGPACK:
|
||||
elif content_type == CONTENT_TYPE_MSGPACK \
|
||||
or content_type.content_suffix == CONTENT_TYPE_SUFFIX_MSGPACK:
|
||||
return self.__hcm_msgpack.packb(body)
|
||||
raise ValueError('Unsupported Content Type')
|
||||
|
||||
|
|
59
tests.py
59
tests.py
|
@ -61,10 +61,13 @@ class TestHandler(web.RequestHandler):
|
|||
self.respond()
|
||||
|
||||
def get_request_body(self):
|
||||
if 'Content-Type' in self.request.headers:
|
||||
if self.request.headers['Content-Type'] == 'application/json':
|
||||
content_type = self.request.headers.get('Content-Type')
|
||||
if content_type is not None:
|
||||
if content_type == 'application/json' \
|
||||
or content_type.endswith('+json'):
|
||||
return json.loads(self.request.body.decode('utf-8'))
|
||||
elif self.request.headers['Content-Type'] == 'application/msgpack':
|
||||
elif content_type == 'application/msgpack' \
|
||||
or content_type.endswith('+msgpack'):
|
||||
return umsgpack.unpackb(self.request.body)
|
||||
if self.request.body_arguments:
|
||||
return self.request.body_arguments
|
||||
|
@ -97,11 +100,13 @@ class TestHandler(web.RequestHandler):
|
|||
|
||||
def send_response(self, payload):
|
||||
if isinstance(payload, (dict, list)):
|
||||
if self.request.headers.get('Accept') == 'application/json':
|
||||
self.set_header('Content-Type', 'application/json')
|
||||
return self.write(decode(payload))
|
||||
elif self.request.headers.get('Accept') == 'application/msgpack':
|
||||
self.set_header('Content-Type', 'application/msgpack')
|
||||
accept = self.request.headers.get('Accept')
|
||||
if accept == 'application/json' or accept.endswith('+json'):
|
||||
self.set_header('Content-Type', accept)
|
||||
return self.write(json.dumps(decode(payload)))
|
||||
elif accept == 'application/msgpack' \
|
||||
or accept.endswith('+msgpack'):
|
||||
self.set_header('Content-Type', accept)
|
||||
return self.write(umsgpack.packb(decode(payload)))
|
||||
LOGGER.debug('Bypassed serialization')
|
||||
content_type = self.get_argument('content_type', None)
|
||||
|
@ -750,3 +755,41 @@ class MixinTestCase(testing.AsyncHTTPTestCase):
|
|||
request_headers={'Content-Type': 'application/json'})
|
||||
self.assertEqual(200, response.code)
|
||||
self.assertEqual([], response.body['body'])
|
||||
|
||||
@testing.gen_test
|
||||
def test_post_msgpack_suffix(self):
|
||||
body = {
|
||||
'foo': 'bar',
|
||||
'status_code': 200
|
||||
}
|
||||
response = yield self.mixin.http_fetch(
|
||||
self.get_url('/test'),
|
||||
method='POST',
|
||||
body=body,
|
||||
request_headers={
|
||||
'Accept': 'bar/foo+msgpack',
|
||||
'Content-Type': 'foo/bar+msgpack'
|
||||
})
|
||||
self.assertEqual(response.code, 200)
|
||||
self.assertEqual(response.headers['Content-Type'],
|
||||
'bar/foo+msgpack')
|
||||
self.assertEqual(response.body['body'], body)
|
||||
|
||||
@testing.gen_test
|
||||
def test_post_json_suffix(self):
|
||||
body = {
|
||||
'foo': 'bar',
|
||||
'status_code': 200
|
||||
}
|
||||
response = yield self.mixin.http_fetch(
|
||||
self.get_url('/test'),
|
||||
method='POST',
|
||||
body=body,
|
||||
request_headers={
|
||||
'Accept': 'bar/foo+json',
|
||||
'Content-Type': 'foo/bar+json'
|
||||
})
|
||||
self.assertEqual(response.code, 200)
|
||||
self.assertEqual(response.headers['Content-Type'],
|
||||
'bar/foo+json')
|
||||
self.assertEqual(response.body['body'], body)
|
||||
|
|
Loading…
Reference in a new issue