Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/routes/middleware.py @ 5:9b1c78e6ba9c draft default tip
"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author | shellac |
---|---|
date | Mon, 01 Jun 2020 08:59:25 -0400 |
parents | 79f47841a781 |
children |
comparison
equal
deleted
inserted
replaced
4:79f47841a781 | 5:9b1c78e6ba9c |
---|---|
1 """Routes WSGI Middleware""" | |
2 import re | |
3 import logging | |
4 | |
5 from webob import Request | |
6 | |
7 from routes.base import request_config | |
8 from routes.util import URLGenerator | |
9 | |
10 log = logging.getLogger('routes.middleware') | |
11 | |
12 | |
13 class RoutesMiddleware(object): | |
14 """Routing middleware that handles resolving the PATH_INFO in | |
15 addition to optionally recognizing method overriding. | |
16 | |
17 .. Note:: | |
18 This module requires webob to be installed. To depend on it, you may | |
19 list routes[middleware] in your ``requirements.txt`` | |
20 """ | |
21 def __init__(self, wsgi_app, mapper, use_method_override=True, | |
22 path_info=True, singleton=True): | |
23 """Create a Route middleware object | |
24 | |
25 Using the use_method_override keyword will require Paste to be | |
26 installed, and your application should use Paste's WSGIRequest | |
27 object as it will properly handle POST issues with wsgi.input | |
28 should Routes check it. | |
29 | |
30 If path_info is True, then should a route var contain | |
31 path_info, the SCRIPT_NAME and PATH_INFO will be altered | |
32 accordingly. This should be used with routes like: | |
33 | |
34 .. code-block:: python | |
35 | |
36 map.connect('blog/*path_info', controller='blog', path_info='') | |
37 | |
38 """ | |
39 self.app = wsgi_app | |
40 self.mapper = mapper | |
41 self.singleton = singleton | |
42 self.use_method_override = use_method_override | |
43 self.path_info = path_info | |
44 self.log_debug = logging.DEBUG >= log.getEffectiveLevel() | |
45 if self.log_debug: | |
46 log.debug("Initialized with method overriding = %s, and path " | |
47 "info altering = %s", use_method_override, path_info) | |
48 | |
49 def __call__(self, environ, start_response): | |
50 """Resolves the URL in PATH_INFO, and uses wsgi.routing_args | |
51 to pass on URL resolver results.""" | |
52 old_method = None | |
53 if self.use_method_override: | |
54 req = None | |
55 | |
56 # In some odd cases, there's no query string | |
57 try: | |
58 qs = environ['QUERY_STRING'] | |
59 except KeyError: | |
60 qs = '' | |
61 if '_method' in qs: | |
62 req = Request(environ) | |
63 req.errors = 'ignore' | |
64 if '_method' in req.GET: | |
65 old_method = environ['REQUEST_METHOD'] | |
66 environ['REQUEST_METHOD'] = req.GET['_method'].upper() | |
67 if self.log_debug: | |
68 log.debug("_method found in QUERY_STRING, altering " | |
69 "request method to %s", | |
70 environ['REQUEST_METHOD']) | |
71 elif environ['REQUEST_METHOD'] == 'POST' and is_form_post(environ): | |
72 if req is None: | |
73 req = Request(environ) | |
74 req.errors = 'ignore' | |
75 if '_method' in req.POST: | |
76 old_method = environ['REQUEST_METHOD'] | |
77 environ['REQUEST_METHOD'] = req.POST['_method'].upper() | |
78 if self.log_debug: | |
79 log.debug("_method found in POST data, altering " | |
80 "request method to %s", | |
81 environ['REQUEST_METHOD']) | |
82 | |
83 # Run the actual route matching | |
84 # -- Assignment of environ to config triggers route matching | |
85 if self.singleton: | |
86 config = request_config() | |
87 config.mapper = self.mapper | |
88 config.environ = environ | |
89 match = config.mapper_dict | |
90 route = config.route | |
91 else: | |
92 results = self.mapper.routematch(environ=environ) | |
93 if results: | |
94 match, route = results[0], results[1] | |
95 else: | |
96 match = route = None | |
97 | |
98 if old_method: | |
99 environ['REQUEST_METHOD'] = old_method | |
100 | |
101 if not match: | |
102 match = {} | |
103 if self.log_debug: | |
104 urlinfo = "%s %s" % (environ['REQUEST_METHOD'], | |
105 environ['PATH_INFO']) | |
106 log.debug("No route matched for %s", urlinfo) | |
107 elif self.log_debug: | |
108 urlinfo = "%s %s" % (environ['REQUEST_METHOD'], | |
109 environ['PATH_INFO']) | |
110 log.debug("Matched %s", urlinfo) | |
111 log.debug("Route path: '%s', defaults: %s", route.routepath, | |
112 route.defaults) | |
113 log.debug("Match dict: %s", match) | |
114 | |
115 url = URLGenerator(self.mapper, environ) | |
116 environ['wsgiorg.routing_args'] = ((url), match) | |
117 environ['routes.route'] = route | |
118 environ['routes.url'] = url | |
119 | |
120 if route and route.redirect: | |
121 route_name = '_redirect_%s' % id(route) | |
122 location = url(route_name, **match) | |
123 log.debug("Using redirect route, redirect to '%s' with status" | |
124 "code: %s", location, route.redirect_status) | |
125 start_response(route.redirect_status, | |
126 [('Content-Type', 'text/plain; charset=utf8'), | |
127 ('Location', location)]) | |
128 return [] | |
129 | |
130 # If the route included a path_info attribute and it should be used to | |
131 # alter the environ, we'll pull it out | |
132 if self.path_info and 'path_info' in match: | |
133 oldpath = environ['PATH_INFO'] | |
134 newpath = match.get('path_info') or '' | |
135 environ['PATH_INFO'] = newpath | |
136 if not environ['PATH_INFO'].startswith('/'): | |
137 environ['PATH_INFO'] = '/' + environ['PATH_INFO'] | |
138 environ['SCRIPT_NAME'] += re.sub( | |
139 r'^(.*?)/' + re.escape(newpath) + '$', r'\1', oldpath) | |
140 | |
141 response = self.app(environ, start_response) | |
142 | |
143 # Wrapped in try as in rare cases the attribute will be gone already | |
144 try: | |
145 del self.mapper.environ | |
146 except AttributeError: | |
147 pass | |
148 return response | |
149 | |
150 | |
151 def is_form_post(environ): | |
152 """Determine whether the request is a POSTed html form""" | |
153 content_type = environ.get('CONTENT_TYPE', '').lower() | |
154 if ';' in content_type: | |
155 content_type = content_type.split(';', 1)[0] | |
156 return content_type in ('application/x-www-form-urlencoded', | |
157 'multipart/form-data') |