New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Path is always set to "/" using unicode wsgi protocol under Python 3 #1350

Closed
bb-migration opened this Issue Dec 29, 2014 · 7 comments

Comments

Projects
None yet
5 participants
@bb-migration

bb-migration commented Dec 29, 2014

Originally reported by: Lars Gustäbel (Bitbucket: gustaebel, GitHub: gustaebel)


I am using a cherrypy server with wsgi_version = ("u", 0) under Python 3, and found a bug in _cherrypy.cptree.Tree.call().

The problematic code is the following:

#!python

env1x = environ
if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
    env1x = _cpwsgi.downgrade_wsgi_ux_to_1x(environ)
path = httputil.urljoin(env1x.get('SCRIPT_NAME', ''),
                        env1x.get('PATH_INFO', ''))
sn = self.script_name(path or "/")

The unicode environment is converted to bytes (in Python 3) in order to assemble the path from SCRIPT_NAME and PATH_INFO. The problem is that after this conversion all keys are bytes objects, so both env1x.get() calls fail and return the empty string. This in turn leads to httputil.urljoin() returning the empty string which is then replaced by "/" in the script_name() call.

So, whatever url you pass to Tree.call() they all get converted to "/". My solution to this problem is to test for py3k before downgrade_wsgi_ux_to_1x(). A patch is attached.

#!python

if py3k:
    if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
        env1x = _cpwsgi.downgrade_wsgi_ux_to_1x(environ)

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Mar 29, 2016

Original comment by David Eriksson (Bitbucket: softhousedae, GitHub: Unknown):


Not fixed in over a year even when there is a patch? :-(

Runtime workaround:

#!python

cherrypy._cpwsgi.downgrade_wsgi_ux_to_1x = lambda env: env

bb-migration commented Mar 29, 2016

Original comment by David Eriksson (Bitbucket: softhousedae, GitHub: Unknown):


Not fixed in over a year even when there is a patch? :-(

Runtime workaround:

#!python

cherrypy._cpwsgi.downgrade_wsgi_ux_to_1x = lambda env: env
@webknjaz

This comment has been minimized.

Show comment
Hide comment
@webknjaz

webknjaz Sep 23, 2016

Member

@gustaebel @twogood could you please confirm that the issue still exists for the latest version of CherryPy?

Member

webknjaz commented Sep 23, 2016

@gustaebel @twogood could you please confirm that the issue still exists for the latest version of CherryPy?

@twogood

This comment has been minimized.

Show comment
Hide comment
@twogood

twogood Sep 23, 2016

@webknjaz For various reasons I'm still stuck on an old version of CherryPy, thanks for reminding me of upgrading. I did try a newer version at some point, but my application broke down, so there will be Work involved... :-)

twogood commented Sep 23, 2016

@webknjaz For various reasons I'm still stuck on an old version of CherryPy, thanks for reminding me of upgrading. I did try a newer version at some point, but my application broke down, so there will be Work involved... :-)

@gustaebel

This comment has been minimized.

Show comment
Hide comment
@gustaebel

gustaebel Sep 26, 2016

I tried the version 8.1.0 of cherrypy but got the following traceback:

Traceback (most recent call last):
  File "/usr/lib/python3.5/site-packages/cherrypy/wsgiserver/__init__.py", line 1406, in communicate
    req.respond()
  File "/usr/lib/python3.5/site-packages/cherrypy/wsgiserver/__init__.py", line 860, in respond
    self.server.gateway(self).respond()
  File "/usr/lib/python3.5/site-packages/cherrypy/wsgiserver/__init__.py", line 2310, in __init__
    self.env = self.get_environ()
  File "/usr/lib/python3.5/site-packages/cherrypy/wsgiserver/__init__.py", line 2498, in get_environ
    env = dict(map(self._decode_key, self.items()))
AttributeError: 'WSGIGateway_u0' object has no attribute 'items'

With the following patch applied, all seems to work well :-)

diff --git a/cherrypy/wsgiserver/__init__.py b/cherrypy/wsgiserver/__init__.py
index 77fb361..98607e4 100644
--- a/cherrypy/wsgiserver/__init__.py
+++ b/cherrypy/wsgiserver/__init__.py
@@ -2497,7 +2497,7 @@ class WSGIGateway_u0(WSGIGateway_10):
         """Return a new environ dict targeting the given wsgi.version"""
         req = self.req
         env_10 = WSGIGateway_10.get_environ(self)
-        env = dict(map(self._decode_key, self.items()))
+        env = dict(self._decode_key(k, v) for k, v in env_10.items())
         env[six.u('wsgi.version')] = ('u', 0)

         # Request-URI
@@ -2511,7 +2511,7 @@ class WSGIGateway_u0(WSGIGateway_10):
             env['PATH_INFO'] = env_10['PATH_INFO']
             env['QUERY_STRING'] = env_10['QUERY_STRING']

-        env.update(map(self._decode_value, self.items()))
+        env.update(dict(self._decode_value(k, v) for k, v in env_10.items()))

         return env

gustaebel commented Sep 26, 2016

I tried the version 8.1.0 of cherrypy but got the following traceback:

Traceback (most recent call last):
  File "/usr/lib/python3.5/site-packages/cherrypy/wsgiserver/__init__.py", line 1406, in communicate
    req.respond()
  File "/usr/lib/python3.5/site-packages/cherrypy/wsgiserver/__init__.py", line 860, in respond
    self.server.gateway(self).respond()
  File "/usr/lib/python3.5/site-packages/cherrypy/wsgiserver/__init__.py", line 2310, in __init__
    self.env = self.get_environ()
  File "/usr/lib/python3.5/site-packages/cherrypy/wsgiserver/__init__.py", line 2498, in get_environ
    env = dict(map(self._decode_key, self.items()))
AttributeError: 'WSGIGateway_u0' object has no attribute 'items'

With the following patch applied, all seems to work well :-)

diff --git a/cherrypy/wsgiserver/__init__.py b/cherrypy/wsgiserver/__init__.py
index 77fb361..98607e4 100644
--- a/cherrypy/wsgiserver/__init__.py
+++ b/cherrypy/wsgiserver/__init__.py
@@ -2497,7 +2497,7 @@ class WSGIGateway_u0(WSGIGateway_10):
         """Return a new environ dict targeting the given wsgi.version"""
         req = self.req
         env_10 = WSGIGateway_10.get_environ(self)
-        env = dict(map(self._decode_key, self.items()))
+        env = dict(self._decode_key(k, v) for k, v in env_10.items())
         env[six.u('wsgi.version')] = ('u', 0)

         # Request-URI
@@ -2511,7 +2511,7 @@ class WSGIGateway_u0(WSGIGateway_10):
             env['PATH_INFO'] = env_10['PATH_INFO']
             env['QUERY_STRING'] = env_10['QUERY_STRING']

-        env.update(map(self._decode_value, self.items()))
+        env.update(dict(self._decode_value(k, v) for k, v in env_10.items()))

         return env

@webknjaz

This comment has been minimized.

Show comment
Hide comment
@webknjaz

webknjaz Sep 26, 2016

Member

@gustaebel feel free to send a PR along with tests

Member

webknjaz commented Sep 26, 2016

@gustaebel feel free to send a PR along with tests

@jaraco

This comment has been minimized.

Show comment
Hide comment
@jaraco

jaraco Sep 28, 2016

Member

It seems like the use of self.items is a bug going back to f2ec506.

Member

jaraco commented Sep 28, 2016

It seems like the use of self.items is a bug going back to f2ec506.

@jaraco

This comment has been minimized.

Show comment
Hide comment
@jaraco

jaraco Mar 12, 2017

Member

Meant to mention this ticket in 481b6f9, but mistakenly mentioned another.

Member

jaraco commented Mar 12, 2017

Meant to mention this ticket in 481b6f9, but mistakenly mentioned another.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment