hgweb: ensure all wsgi environment values are str
authorGregory Szorc <gregory.szorc@gmail.com>
Thu, 08 Mar 2018 09:26:51 -0800
changeset 36802 7fc80c982656
parent 36801 66de4555cefd
child 36803 8e1556ac01bb
hgweb: ensure all wsgi environment values are str Previously, we had a few entries that were bytes on Python 3. PEP-0333 states that all entries must be the native str type (bytes on Python 2, str on Python 3). This required a number of changes to hgweb_mod to unbreak things on Python 3. I suspect there still may be some regressions. I'm going to introduce a data structure that represents a parsed WSGI request in upcoming commits. This will hold bytes and will allow us to stop using raw literals throughout the WSGI code. Differential Revision: https://phab.mercurial-scm.org/D2730
mercurial/hgweb/hgweb_mod.py
mercurial/hgweb/server.py
--- a/mercurial/hgweb/hgweb_mod.py	Wed Mar 07 16:18:52 2018 -0800
+++ b/mercurial/hgweb/hgweb_mod.py	Thu Mar 08 09:26:51 2018 -0800
@@ -159,7 +159,8 @@
         urlbase = r'%s://%s%s' % (proto, req.env[r'SERVER_NAME'], port)
         logourl = self.config('web', 'logourl')
         logoimg = self.config('web', 'logoimg')
-        staticurl = self.config('web', 'staticurl') or req.url + 'static/'
+        staticurl = (self.config('web', 'staticurl')
+                     or pycompat.sysbytes(req.url) + 'static/')
         if not staticurl.endswith('/'):
             staticurl += '/'
 
@@ -182,7 +183,7 @@
         if not self.reponame:
             self.reponame = (self.config('web', 'name', '')
                              or req.env.get('REPO_NAME')
-                             or req.url.strip('/') or self.repo.root)
+                             or req.url.strip(r'/') or self.repo.root)
 
         def websubfilter(text):
             return templatefilters.websub(text, self.websubtable)
@@ -190,7 +191,7 @@
         # create the templater
         # TODO: export all keywords: defaults = templatekw.keywords.copy()
         defaults = {
-            'url': req.url,
+            'url': pycompat.sysbytes(req.url),
             'logourl': logourl,
             'logoimg': logoimg,
             'staticurl': staticurl,
@@ -199,7 +200,7 @@
             'encoding': encoding.encoding,
             'motd': motd,
             'sessionvars': sessionvars,
-            'pathdef': makebreadcrumb(req.url),
+            'pathdef': makebreadcrumb(pycompat.sysbytes(req.url)),
             'style': style,
             'nonce': self.nonce,
         }
@@ -333,17 +334,17 @@
         # use SCRIPT_NAME, PATH_INFO and QUERY_STRING as well as our REPO_NAME
 
         req.url = req.env[r'SCRIPT_NAME']
-        if not req.url.endswith('/'):
-            req.url += '/'
+        if not req.url.endswith(r'/'):
+            req.url += r'/'
         if req.env.get('REPO_NAME'):
             req.url += req.env[r'REPO_NAME'] + r'/'
 
         if r'PATH_INFO' in req.env:
-            parts = req.env[r'PATH_INFO'].strip('/').split('/')
+            parts = req.env[r'PATH_INFO'].strip(r'/').split(r'/')
             repo_parts = req.env.get(r'REPO_NAME', r'').split(r'/')
             if parts[:len(repo_parts)] == repo_parts:
                 parts = parts[len(repo_parts):]
-            query = '/'.join(parts)
+            query = r'/'.join(parts)
         else:
             query = req.env[r'QUERY_STRING'].partition(r'&')[0]
             query = query.partition(r';')[0]
@@ -364,7 +365,7 @@
 
         # translate user-visible url structure to internal structure
 
-        args = query.split('/', 2)
+        args = query.split(r'/', 2)
         if 'cmd' not in req.form and args and args[0]:
             cmd = args.pop(0)
             style = cmd.rfind('-')
--- a/mercurial/hgweb/server.py	Wed Mar 07 16:18:52 2018 -0800
+++ b/mercurial/hgweb/server.py	Thu Mar 08 09:26:51 2018 -0800
@@ -124,8 +124,8 @@
         env[r'SERVER_NAME'] = self.server.server_name
         env[r'SERVER_PORT'] = str(self.server.server_port)
         env[r'REQUEST_URI'] = self.path
-        env[r'SCRIPT_NAME'] = self.server.prefix
-        env[r'PATH_INFO'] = path[len(self.server.prefix):]
+        env[r'SCRIPT_NAME'] = pycompat.sysstr(self.server.prefix)
+        env[r'PATH_INFO'] = pycompat.sysstr(path[len(self.server.prefix):])
         env[r'REMOTE_HOST'] = self.client_address[0]
         env[r'REMOTE_ADDR'] = self.client_address[0]
         if query:
@@ -154,7 +154,7 @@
                 env[hkey] = hval
         env[r'SERVER_PROTOCOL'] = self.request_version
         env[r'wsgi.version'] = (1, 0)
-        env[r'wsgi.url_scheme'] = self.url_scheme
+        env[r'wsgi.url_scheme'] = pycompat.sysstr(self.url_scheme)
         if env.get(r'HTTP_EXPECT', '').lower() == '100-continue':
             self.rfile = common.continuereader(self.rfile, self.wfile.write)