Skip to content

Commit

Permalink
Make HTTPResponse.getHeaders() deterministic
Browse files Browse the repository at this point in the history
Fixes #8.
  • Loading branch information
mgedmin committed Nov 9, 2015
1 parent 57a3cee commit 22cad77
Show file tree
Hide file tree
Showing 3 changed files with 3 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/zope/publisher/http.py
Expand Up @@ -721,7 +721,7 @@ def getHeaders(self):
result.append(
("X-Powered-By", "Zope (www.zope.org), Python (www.python.org)"))

for key, values in headers.items():
for key, values in sorted(headers.items(), key=lambda x: x[0].lower()):
if key.lower() == key:
# only change non-literal header names
key = '-'.join([k.capitalize() for k in key.split('-')])
Expand Down
2 changes: 1 addition & 1 deletion src/zope/publisher/tests/test_browserrequest.py
Expand Up @@ -152,10 +152,10 @@ def testTraversalToItem(self):
self.assertEqual(
res,
"Status: 200 Ok\r\n"
"X-Powered-By: Zope (www.zope.org), Python (www.python.org)\r\n"
"Content-Length: 6\r\n"
"Content-Type: text/plain;charset=utf-8\r\n"
"X-Content-Type-Warning: guessed from content\r\n"
"X-Powered-By: Zope (www.zope.org), Python (www.python.org)\r\n"

This comment has been minimized.

Copy link
@tseaver

tseaver Nov 9, 2015

Member

How is this a fix? The headers still aren't in sorted order.

This comment has been minimized.

Copy link
@mgedmin

mgedmin Nov 10, 2015

Author Member

The order is not alphabetical, but it's deterministic:

  • Status is not a header
  • X-Powered-By is always the 1st header
  • then come user-provided headers, sorted alphabetically (this is the part that I changed -- previously user-supplied headers came in dictionary order)
  • then come Set-Cookie headers, with cookie names sorted alphabetically (by the Cookie stdlib module)
"\r\n"
"'5', 6")

Expand Down
3 changes: 1 addition & 2 deletions src/zope/publisher/tests/test_http.py
Expand Up @@ -236,7 +236,6 @@ def _publisherResults(self, extra_env={}, body=b""):
response = request.response
publish(request, handle_errors=False)
headers = response.getHeaders()
headers.sort()
return (
"Status: %s\r\n" % response.getStatusString()
+
Expand Down Expand Up @@ -273,8 +272,8 @@ def testTraversalToItem(self):
self.assertEqual(
res,
"Status: 200 Ok\r\n"
"Content-Length: 6\r\n"
"X-Powered-By: Zope (www.zope.org), Python (www.python.org)\r\n"
"Content-Length: 6\r\n"
"\r\n"
"'5', 6")

Expand Down

0 comments on commit 22cad77

Please sign in to comment.