fix: Refine client_accepts
This commit is contained in:
@@ -31,8 +31,6 @@ DEFAULT_ERROR_LOG_FORMAT = (u'{0:%Y-%m-%d %H:%M:%S} [FALCON] [ERROR]'
|
||||
TRUE_STRINGS = ('true', 'True', 'yes')
|
||||
FALSE_STRINGS = ('false', 'False', 'no')
|
||||
|
||||
MEDIA_TYPES_XML = ('application/xml', 'text/xml')
|
||||
|
||||
|
||||
class InvalidHeaderValueError(HTTPBadRequest):
|
||||
def __init__(self, msg, href=None, href_text=None):
|
||||
@@ -152,14 +150,13 @@ class Request(object):
|
||||
@property
|
||||
def client_accepts_xml(self):
|
||||
"""Return True if the Accept header indicates XML support."""
|
||||
return self.client_accepts(MEDIA_TYPES_XML)
|
||||
return self.client_accepts('application/xml')
|
||||
|
||||
def client_accepts(self, media_types):
|
||||
def client_accepts(self, media_type):
|
||||
"""Returns the client's preferred media type.
|
||||
|
||||
Args:
|
||||
media_types: One or more media types. May be a single string (
|
||||
of type str), or an iterable collection of strings.
|
||||
media_type: Media type to check
|
||||
|
||||
Returns:
|
||||
True IFF the client has indicated in the Accept header that
|
||||
@@ -170,23 +167,14 @@ class Request(object):
|
||||
|
||||
# PERF(kgriffs): Usually the following will be true, so
|
||||
# try it first.
|
||||
if isinstance(media_types, str):
|
||||
if (accept == media_types) or (accept == '*/*'):
|
||||
return accept
|
||||
|
||||
# NOTE(kgriffs): Convert to a collection to be compatible
|
||||
# with mimeparse.best_matchapplication/xhtml+xml
|
||||
media_types = (media_types,)
|
||||
|
||||
# NOTE(kgriffs): Heuristic to quickly check another common case. If
|
||||
# accept is a single type, and it is found in media_types verbatim,
|
||||
# return the media type immediately.
|
||||
elif accept in media_types:
|
||||
return accept
|
||||
if (accept == media_type) or (accept == '*/*'):
|
||||
return True
|
||||
|
||||
# Fall back to full-blown parsing
|
||||
preferred_type = self.client_prefers(media_types)
|
||||
return preferred_type is not None
|
||||
try:
|
||||
return mimeparse.quality(media_type, accept) != 0.0
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
def client_prefers(self, media_types):
|
||||
"""Returns the client's preferred media type given several choices.
|
||||
|
||||
@@ -87,31 +87,27 @@ class TestReqVars(testing.TestBase):
|
||||
headers = {'Accept': 'application/xml'}
|
||||
req = Request(testing.create_environ(headers=headers))
|
||||
self.assertTrue(req.client_accepts('application/xml'))
|
||||
self.assertTrue(req.client_accepts(['application/xml']))
|
||||
|
||||
headers = {'Accept': '*/*'}
|
||||
req = Request(testing.create_environ(headers=headers))
|
||||
self.assertTrue(req.client_accepts(['application/xml']))
|
||||
self.assertTrue(req.client_accepts('application/xml'))
|
||||
|
||||
headers = {} # NOTE(kgriffs): Equivalent to '*/*' per RFC
|
||||
req = Request(testing.create_environ(headers=headers))
|
||||
self.assertTrue(req.client_accepts('application/xml'))
|
||||
self.assertTrue(req.client_accepts(['application/xml']))
|
||||
|
||||
headers = {'Accept': 'application/json'}
|
||||
req = Request(testing.create_environ(headers=headers))
|
||||
self.assertFalse(req.client_accepts(['application/xml']))
|
||||
self.assertFalse(req.client_accepts('application/xml'))
|
||||
|
||||
headers = {'Accept': 'application/xm'}
|
||||
req = Request(testing.create_environ(headers=headers))
|
||||
self.assertFalse(req.client_accepts(['application/xml']))
|
||||
self.assertFalse(req.client_accepts('application/xml'))
|
||||
|
||||
headers = {'Accept': 'application/*'}
|
||||
req = Request(testing.create_environ(headers=headers))
|
||||
self.assertTrue(req.client_accepts(['application/json']))
|
||||
self.assertTrue(req.client_accepts(['application/xml']))
|
||||
self.assertTrue(req.client_accepts(['application/json',
|
||||
'application/xml']))
|
||||
self.assertTrue(req.client_accepts('application/json'))
|
||||
self.assertTrue(req.client_accepts('application/xml'))
|
||||
|
||||
headers = {'Accept': 'text/*'}
|
||||
req = Request(testing.create_environ(headers=headers))
|
||||
@@ -124,9 +120,6 @@ class TestReqVars(testing.TestBase):
|
||||
self.assertTrue(req.client_accepts('text/plain'))
|
||||
self.assertTrue(req.client_accepts('text/csv'))
|
||||
self.assertTrue(req.client_accepts('application/xhtml+xml'))
|
||||
self.assertTrue(req.client_accepts(('application/xhtml+xml',
|
||||
'text/plain',
|
||||
'text/csv')))
|
||||
|
||||
headers = {'Accept': 'text/*; q=0.1, application/xhtml+xml; q=0.5'}
|
||||
req = Request(testing.create_environ(headers=headers))
|
||||
@@ -148,15 +141,7 @@ class TestReqVars(testing.TestBase):
|
||||
self.assertTrue(req.client_accepts_xml)
|
||||
self.assertFalse(req.client_accepts_json)
|
||||
|
||||
headers = {'Accept': 'text/xml'}
|
||||
req = Request(testing.create_environ(headers=headers))
|
||||
self.assertTrue(req.client_accepts_xml)
|
||||
|
||||
headers = {'Accept': 'text/*'}
|
||||
req = Request(testing.create_environ(headers=headers))
|
||||
self.assertTrue(req.client_accepts_xml)
|
||||
|
||||
headers = {'Accept': 'text/xml, application/xml'}
|
||||
headers = {'Accept': 'application/*'}
|
||||
req = Request(testing.create_environ(headers=headers))
|
||||
self.assertTrue(req.client_accepts_xml)
|
||||
|
||||
@@ -188,6 +173,11 @@ class TestReqVars(testing.TestBase):
|
||||
preferred_type = req.client_prefers(['application/xhtml+xml'])
|
||||
self.assertEquals(preferred_type, 'application/xhtml+xml')
|
||||
|
||||
headers = {'Accept': '3p12845j;;;asfd;'}
|
||||
req = Request(testing.create_environ(headers=headers))
|
||||
preferred_type = req.client_prefers(['application/xhtml+xml'])
|
||||
self.assertEquals(preferred_type, None)
|
||||
|
||||
def test_range(self):
|
||||
headers = {'Range': '10-'}
|
||||
req = Request(testing.create_environ(headers=headers))
|
||||
|
||||
@@ -83,7 +83,9 @@ def to_query_str(params):
|
||||
elif v is False:
|
||||
v = 'false'
|
||||
elif isinstance(v, list):
|
||||
v = ','.join([str(i) for i in v])
|
||||
# PERF(kgriffs): map is faster than list comprehension in
|
||||
# py26 and py33. No significant different in py27
|
||||
v = ','.join(map(str, v))
|
||||
else:
|
||||
v = str(v)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user