Change ASGI spec regarding headers.

This commit is contained in:
Andrew Godwin 2016-03-11 10:20:17 -08:00
parent a06026c99a
commit 820e955515
3 changed files with 30 additions and 13 deletions

View File

@ -58,16 +58,26 @@ class AsgiRequest(http.HttpRequest):
if self.message.get('server', None): if self.message.get('server', None):
self.META['SERVER_NAME'] = self.message['server'][0] self.META['SERVER_NAME'] = self.message['server'][0]
self.META['SERVER_PORT'] = self.message['server'][1] self.META['SERVER_PORT'] = self.message['server'][1]
# Handle old style-headers for a transition period
if "headers" in self.message and isinstance(self.message['headers'], dict):
self.message['headers'] = [
(x.encode("latin1"), y) for x, y in
self.message['headers'].items()
]
# Headers go into META # Headers go into META
for name, value in self.message.get('headers', {}).items(): for name, value in self.message.get('headers', []):
name = name.decode("latin1")
if name == "content-length": if name == "content-length":
corrected_name = "CONTENT_LENGTH" corrected_name = "CONTENT_LENGTH"
elif name == "content-type": elif name == "content-type":
corrected_name = "CONTENT_TYPE" corrected_name = "CONTENT_TYPE"
else: else:
corrected_name = 'HTTP_%s' % name.upper().replace("-", "_") corrected_name = 'HTTP_%s' % name.upper().replace("-", "_")
# HTTPbis say only ASCII chars are allowed in headers # HTTPbis say only ASCII chars are allowed in headers, but we latin1 just in case
self.META[corrected_name] = value.decode("ascii") value = value.decode("latin1")
if corrected_name in self.META:
value = self.META[corrected_name] + "," + value.decode("latin1")
self.META[corrected_name] = value
# Pull out request encoding if we find it # Pull out request encoding if we find it
if "CONTENT_TYPE" in self.META: if "CONTENT_TYPE" in self.META:
_, content_params = cgi.parse_header(self.META["CONTENT_TYPE"]) _, content_params = cgi.parse_header(self.META["CONTENT_TYPE"])
@ -212,13 +222,13 @@ class AsgiHandler(base.BaseHandler):
# compliant clients that want things like Content-Type correct. Ugh. # compliant clients that want things like Content-Type correct. Ugh.
response_headers = [] response_headers = []
for header, value in response.items(): for header, value in response.items():
if isinstance(header, six.binary_type): if isinstance(header, six.text_type):
header = header.decode("latin1") header = header.encode("ascii")
if isinstance(value, six.text_type): if isinstance(value, six.text_type):
value = value.encode("latin1") value = value.encode("latin1")
response_headers.append( response_headers.append(
( (
six.text_type(header), six.binary_type(header),
six.binary_type(value), six.binary_type(value),
) )
) )

View File

@ -30,5 +30,11 @@ class Message(object):
def __getitem__(self, key): def __getitem__(self, key):
return self.content[key] return self.content[key]
def __setitem__(self, key, value):
self.content[key] = value
def __contains__(self, key):
return key in self.content
def get(self, key, default=None): def get(self, key, default=None):
return self.content.get(key, default) return self.content.get(key, default)

View File

@ -454,11 +454,11 @@ Keys:
is mounted at; same as ``SCRIPT_NAME`` in WSGI. Optional, defaults is mounted at; same as ``SCRIPT_NAME`` in WSGI. Optional, defaults
to ``""``. to ``""``.
* ``headers``: Dict of ``{name: value}``, where ``name`` is the lowercased * ``headers``: A list of ``[name, value]`` pairs, where ``name`` is the
HTTP header name as unicode string and ``value`` is the header value as a byte byte string header name, and ``value`` is the byte string
string. If multiple headers with the same name are received, they should header value. Order should be preserved from the original HTTP request;
be concatenated into a single header as per RFC 7230. Header names containing duplicates are possible and must be preserved in the message as received.
underscores should be discarded by the server. Optional, defaults to ``{}``. Header names must be lowercased.
* ``body``: Body of the request, as a byte string. Optional, defaults to ``""``. * ``body``: Body of the request, as a byte string. Optional, defaults to ``""``.
If ``body_channel`` is set, treat as start of body and concatenate If ``body_channel`` is set, treat as start of body and concatenate
@ -514,8 +514,9 @@ Keys:
or left as empty string if no default found. or left as empty string if no default found.
* ``headers``: A list of ``[name, value]`` pairs, where ``name`` is the * ``headers``: A list of ``[name, value]`` pairs, where ``name`` is the
unicode string header name, and ``value`` is the byte string byte string header name, and ``value`` is the byte string
header value. Order should be preserved in the HTTP response. header value. Order should be preserved in the HTTP response. Header names
must be lowercased.
* ``content``: Byte string of HTTP body content. * ``content``: Byte string of HTTP body content.
Optional, defaults to empty string. Optional, defaults to empty string.