##// END OF EJS Templates
py3: fix non-ASCII URLs - decode unicode correctly before passing them to controllers as unicode strings...
Mads Kiilerich -
r8082:6c381371 default
parent child Browse files
Show More
@@ -19,14 +19,34 b' may take precedent over the more generic'
19 refer to the routes manual at http://routes.groovie.org/docs/
19 refer to the routes manual at http://routes.groovie.org/docs/
20 """
20 """
21
21
22 from routes import Mapper
22 import routes
23 from tg import request
23 from tg import request
24
24
25 from kallithea.lib.utils2 import safe_str
26
25
27
26 # prefix for non repository related links needs to be prefixed with `/`
28 # prefix for non repository related links needs to be prefixed with `/`
27 ADMIN_PREFIX = '/_admin'
29 ADMIN_PREFIX = '/_admin'
28
30
29
31
32 class Mapper(routes.Mapper):
33 """
34 Subclassed Mapper with routematch patched to decode "unicode" str url to
35 *real* unicode str before applying matches and invoking controller methods.
36 """
37
38 def routematch(self, url=None, environ=None):
39 """
40 routematch that also decode url from "fake bytes" to real unicode
41 string before matching and invoking controllers.
42 """
43 # Process url like get_path_info does ... but PATH_INFO has already
44 # been retrieved from environ and is passed, so - let's just use that
45 # instead.
46 url = safe_str(url.encode('latin1'))
47 return super().routematch(url=url, environ=environ)
48
49
30 def make_map(config):
50 def make_map(config):
31 """Create, configure and return the routes Mapper"""
51 """Create, configure and return the routes Mapper"""
32 rmap = Mapper(directory=config['paths']['controllers'],
52 rmap = Mapper(directory=config['paths']['controllers'],
@@ -97,12 +97,17 b' def _get_ip_addr(environ):'
97
97
98
98
99 def get_path_info(environ):
99 def get_path_info(environ):
100 """Return unicode PATH_INFO from environ ... using tg.original_request if available.
100 """Return PATH_INFO from environ ... using tg.original_request if available.
101
102 In Python 3 WSGI, PATH_INFO is a unicode str, but kind of contains encoded
103 bytes. The code points are guaranteed to only use the lower 8 bit bits, and
104 encoding the string with the 1:1 encoding latin1 will give the
105 corresponding byte string ... which then can be decoded to proper unicode.
101 """
106 """
102 org_req = environ.get('tg.original_request')
107 org_req = environ.get('tg.original_request')
103 if org_req is not None:
108 if org_req is not None:
104 environ = org_req.environ
109 environ = org_req.environ
105 return safe_str(environ['PATH_INFO'])
110 return safe_str(environ['PATH_INFO'].encode('latin1'))
106
111
107
112
108 def log_in_user(user, remember, is_external_auth, ip_addr):
113 def log_in_user(user, remember, is_external_auth, ip_addr):
@@ -33,9 +33,9 b' class PermanentRepoUrl(object):'
33 def __call__(self, environ, start_response):
33 def __call__(self, environ, start_response):
34 # Extract path_info as get_path_info does, but do it explicitly because
34 # Extract path_info as get_path_info does, but do it explicitly because
35 # we also have to do the reverse operation when patching it back in
35 # we also have to do the reverse operation when patching it back in
36 path_info = safe_str(environ['PATH_INFO'])
36 path_info = safe_str(environ['PATH_INFO'].encode('latin1'))
37 if path_info.startswith('/'): # it must
37 if path_info.startswith('/'): # it must
38 path_info = '/' + fix_repo_id_name(path_info[1:])
38 path_info = '/' + fix_repo_id_name(path_info[1:])
39 environ['PATH_INFO'] = safe_bytes(path_info)
39 environ['PATH_INFO'] = safe_bytes(path_info).decode('latin1')
40
40
41 return self.application(environ, start_response)
41 return self.application(environ, start_response)
General Comments 0
You need to be logged in to leave comments. Login now