hgweb: parse and store HTTP request headers
authorGregory Szorc <gregory.szorc@gmail.com>
Thu, 08 Mar 2018 16:22:25 -0800
changeset 36814 f9078c6caeb6
parent 36813 5a3c83412f79
child 36815 f4e9e89330d4
hgweb: parse and store HTTP request headers WSGI transmits HTTP request headers as HTTP_* environment variables. We teach our parser about these and hook up a dict-like data structure that supports case insensitive header manipulation. Differential Revision: https://phab.mercurial-scm.org/D2742
mercurial/hgweb/hgweb_mod.py
mercurial/hgweb/request.py
--- a/mercurial/hgweb/hgweb_mod.py	Thu Mar 08 16:43:32 2018 -0800
+++ b/mercurial/hgweb/hgweb_mod.py	Thu Mar 08 16:22:25 2018 -0800
@@ -351,7 +351,7 @@
                 if args:
                     wsgireq.form['file'] = args
 
-            ua = wsgireq.env.get('HTTP_USER_AGENT', '')
+            ua = req.headers.get('User-Agent', '')
             if cmd == 'rev' and 'mercurial' in ua:
                 wsgireq.form['style'] = ['raw']
 
--- a/mercurial/hgweb/request.py	Thu Mar 08 16:43:32 2018 -0800
+++ b/mercurial/hgweb/request.py	Thu Mar 08 16:22:25 2018 -0800
@@ -11,6 +11,7 @@
 import cgi
 import errno
 import socket
+import wsgiref.headers as wsgiheaders
 #import wsgiref.validate
 
 from .common import (
@@ -85,6 +86,9 @@
     querystringlist = attr.ib()
     # Dict of query string arguments. Values are lists with at least 1 item.
     querystringdict = attr.ib()
+    # wsgiref.headers.Headers instance. Operates like a dict with case
+    # insensitive keys.
+    headers = attr.ib()
 
 def parserequestfromenv(env):
     """Parse URL components from environment variables.
@@ -186,6 +190,16 @@
         else:
             querystringdict[k] = [v]
 
+    # HTTP_* keys contain HTTP request headers. The Headers structure should
+    # perform case normalization for us. We just rewrite underscore to dash
+    # so keys match what likely went over the wire.
+    headers = []
+    for k, v in env.iteritems():
+        if k.startswith('HTTP_'):
+            headers.append((k[len('HTTP_'):].replace('_', '-'), v))
+
+    headers = wsgiheaders.Headers(headers)
+
     return parsedrequest(url=fullurl, baseurl=baseurl,
                          advertisedurl=advertisedfullurl,
                          advertisedbaseurl=advertisedbaseurl,
@@ -194,7 +208,8 @@
                          havepathinfo='PATH_INFO' in env,
                          querystring=querystring,
                          querystringlist=querystringlist,
-                         querystringdict=querystringdict)
+                         querystringdict=querystringdict,
+                         headers=headers)
 
 class wsgirequest(object):
     """Higher-level API for a WSGI request.