Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/routes/middleware.py @ 2:6af9afd405e9 draft
"planemo upload commit 0a63dd5f4d38a1f6944587f52a8cd79874177fc1"
| author | shellac |
|---|---|
| date | Thu, 14 May 2020 14:56:58 -0400 |
| parents | 26e78fe6e8c4 |
| children |
comparison
equal
deleted
inserted
replaced
| 1:75ca89e9b81c | 2:6af9afd405e9 |
|---|---|
| 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') |
