root/galaxy-central/eggs/Routes-1.12.3-py2.6.egg/routes/middleware.py @ 3

リビジョン 3, 6.0 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

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