summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBert JW Regeer <bertjw@regeer.org>2016-09-29 23:01:12 -0600
committerBert JW Regeer <bertjw@regeer.org>2016-09-30 22:00:36 -0600
commit35fd5854b4b706adafa4caab43b6bcdcf3e6a934 (patch)
treed957717b94db7ab8c9a6d7c90e8239bcc414bd5b
parente1d90de2b33cca63b4213e4c91d07b7280cf0d81 (diff)
downloadwebob-35fd5854b4b706adafa4caab43b6bcdcf3e6a934.tar.gz
Content-Type is not added if a headerlist is provided
If the user provides a headerlist, Response.__init__ will no longer attempt to set the default Content-Type, nor will __init__ add a charset to any existing Content-Type. The Content-Type will only be set if no headerlist is provided, and the HTTP status code allows for a body. The charset will be set only if there is no charset on the Content-Type provided. Response(headerlist=[], content_type='text/plain', charset='UTF-8') will have a headerlist that is: [('Content-Length', '0')] Response(status='204 No Content') will have a headerlist that is: [] __init__ will now also ignore body/app_iter if the status code has no body. Response(status='204 No Content', app_iter=[b'test']) Will not have a Content-Length, and .body will return b''. If you would like to violate HTTP standards, you may of course do: resp = Response(status='204 No Content') resp.body = b'test' __init__ won't let you create an invalid resonse, what you do with the returned response however is up to you.
-rw-r--r--webob/response.py75
1 files changed, 44 insertions, 31 deletions
diff --git a/webob/response.py b/webob/response.py
index cc5ea34..0809118 100644
--- a/webob/response.py
+++ b/webob/response.py
@@ -212,9 +212,6 @@ class Response(object):
else:
self._headerlist = headerlist
- # Set up the content_type
- content_type = content_type or self.default_content_type
-
# We only set the content_type to the one passed to the constructor or
# the default content type if there is none that exists AND there was
# no headerlist passed. If a headerlist was provided then most likely
@@ -225,25 +222,35 @@ class Response(object):
# Response with empty body, such as Response(status='204 No Content')
# without the default content_type being set
- if (
- self.content_type is None and
- headerlist is None and
- _code_has_body(self.status_code)
- ):
- self.content_type = content_type
+ encoding = None
+ code_has_body = (
+ self._status[0] != '1' and
+ self._status[:3] not in ('204', '304')
+ )
+ if headerlist is None and code_has_body:
+ content_type = content_type or self.default_content_type
- # Set up the charset
- #
- # In contrast with the above, if a charset is not set but there is a
- # content_type we will set the default charset if the content_type
- # allows for a charset.
+ # Check if content_type is set because default_content_type could
+ # be None, in which case there is no content_type
+ if content_type:
+
+ # Set up the charset, if the content_type doesn't already have one
+
+ has_charset = 'charset=' in content_type
- if self.content_type:
- if not self.charset and charset is not _marker:
- self.charset = charset
- elif not self.charset and self.default_charset:
- if _content_type_has_charset(self.content_type):
- self.charset = self.default_charset
+ if not has_charset and charset is not _marker and charset is not None:
+ encoding = charset
+ content_type += '; charset=' + charset
+ elif not has_charset and charset is _marker and self.default_charset:
+ # Optimize for the default_content_type case, avoid a function call
+ if (
+ content_type is self.default_content_type or
+ _content_type_has_charset(content_type)
+ ):
+ encoding = self.default_charset
+ content_type += '; charset=' + self.default_charset
+
+ self._headerlist.append(('Content-Type', content_type))
# Set up conditional response
if conditional_response is None:
@@ -251,17 +258,30 @@ class Response(object):
else:
self.conditional_response = bool(conditional_response)
- # Set up app_iter
- if app_iter is None:
+ # Set up app_iter if the HTTP Status code has a body
+ if app_iter is None and code_has_body:
if isinstance(body, text_type):
- encoding = self.charset
+ # Fall back to trying self.charset if encoding is not set. In
+ # most cases encoding will be set to the default value.
+ encoding = encoding or self.charset
if encoding is None:
raise TypeError(
"You cannot set the body to a text value without a "
"charset")
body = body.encode(encoding)
app_iter = [body]
- self.headers['Content-Length'] = str(len(body))
+
+ if headerlist is not None:
+ self._headerlist[:] = [
+ (k, v)
+ for (k, v)
+ in self._headerlist
+ if k.lower() != 'content-length'
+ ]
+ self._headerlist.append(('Content-Length', str(len(body))))
+ elif app_iter is None or not code_has_body:
+ app_iter = [b'']
+
self._app_iter = app_iter
# Loop through all the remaining keyword arguments
@@ -1436,13 +1456,6 @@ class EmptyResponse(object):
__next__ = next # py3
-def _code_has_body(status_code):
- return (
- (not (100 <= status_code < 199)) and
- (status_code != 204) and
- (status_code != 304)
- )
-
def _is_xml(content_type):
return (
content_type.startswith('application/xml') or