Skip to content

Commit 3466ed4

Browse files
committed
Python 3 preparation: HTTP headers handling in roundup_server.py.
HTTP headers are handled differently in Python 3 (where they use email.message.Message) compared to Python 2 (where they use mimetools.Message). In some places the code needs to check which version of the interface is available. For the common case of getting a single header, ".get" is available in both versions, and is an alias of ".getheader" in Python 2. (Note that the Python 3 semantics of ".get" are slightly different from those in Python 2 if there is more than one of a given header - it returns an arbitrary one, when in Python 2 it's specified to return the last one. Hopefully the places using this interface rather than explicitly allowing for multiple headers with the same name are OK with that and it shouldn't actually occur with well-behaved clients.)
1 parent 411f1e9 commit 3466ed4

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

roundup/scripts/roundup_server.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -375,17 +375,28 @@ def inner_run_cgi(self):
375375
env['PATH_INFO'] = urllib_.unquote(rest)
376376
if query:
377377
env['QUERY_STRING'] = query
378-
if self.headers.typeheader is None:
378+
if hasattr(self.headers, 'get_content_type'):
379+
# Python 3. We need the raw header contents.
380+
env['CONTENT_TYPE'] = self.headers.get('content-type')
381+
elif self.headers.typeheader is None:
382+
# Python 2.
379383
env['CONTENT_TYPE'] = self.headers.type
380384
else:
385+
# Python 2.
381386
env['CONTENT_TYPE'] = self.headers.typeheader
382-
length = self.headers.getheader('content-length')
387+
length = self.headers.get('content-length')
383388
if length:
384389
env['CONTENT_LENGTH'] = length
385-
co = list(filter(None, self.headers.getheaders('cookie')))
390+
if hasattr(self.headers, 'get_all'):
391+
# Python 3.
392+
ch = self.headers.get_all('cookie', [])
393+
else:
394+
# Python 2.
395+
ch = self.headers.getheaders('cookie')
396+
co = list(filter(None, ch))
386397
if co:
387398
env['HTTP_COOKIE'] = ', '.join(co)
388-
env['HTTP_AUTHORIZATION'] = self.headers.getheader('authorization')
399+
env['HTTP_AUTHORIZATION'] = self.headers.get('authorization')
389400
env['SCRIPT_NAME'] = ''
390401
env['SERVER_NAME'] = self.server.server_name
391402
env['SERVER_PORT'] = str(self.server.server_port)
@@ -395,13 +406,13 @@ def inner_run_cgi(self):
395406
env['HTTP_HOST'] = ''
396407
# https://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded-10
397408
# headers.
398-
xfh = self.headers.getheader('X-Forwarded-Host', None)
409+
xfh = self.headers.get('X-Forwarded-Host', None)
399410
if xfh:
400411
# If behind a proxy, this is the hostname supplied
401412
# via the Host header to the proxy. Used by core code.
402413
# Controlled by the CSRF settings.
403414
env['HTTP_X-FORWARDED-HOST'] = xfh
404-
xff = self.headers.getheader('X-Forwarded-For', None)
415+
xff = self.headers.get('X-Forwarded-For', None)
405416
if xff:
406417
# xff is a list of ip addresses for original client/proxies:
407418
# X-Forwarded-For: clientIP, proxy1IP, proxy2IP
@@ -411,7 +422,7 @@ def inner_run_cgi(self):
411422
# E.g. you may wish to disable recaptcha validation extension
412423
# if the ip of the client matches 172.16.0.0.
413424
env['HTTP_X-FORWARDED-FOR'] = xff
414-
xfp = self.headers.getheader('X-Forwarded-Proto', None)
425+
xfp = self.headers.get('X-Forwarded-Proto', None)
415426
if xfp:
416427
# xfp is the protocol (http/https) seen by proxies in the
417428
# path of the request. I am not sure if there is only
@@ -437,7 +448,7 @@ def inner_run_cgi(self):
437448
xrw = self.headers.get('x-requested-with')
438449
if xrw:
439450
env['HTTP_X-REQUESTED-WITH'] = xrw
440-
range = self.headers.getheader('range')
451+
range = self.headers.get('range')
441452
if range:
442453
env['HTTP_RANGE'] = range
443454

0 commit comments

Comments
 (0)