Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Ticket #600: forward.patch

  • _cpconfig.py

    old new  
    4848        _cp_config = {'tools.gzip.on': True} 
    4949         
    5050        def index(self): 
    51             raise cherrypy.InternalRedirect("/cuba") 
     51            return "Hello world" 
    5252        index.exposed = True 
    53         index._cp_config = {'request.recursive_redirect': True} 
     53        index._cp_config = {'request.show_tracebacks': False} 
    5454 
    5555 
    5656Namespaces 
  • _cpdispatch.py

    old new  
    308308                merge(app.config[curpath]) 
    309309         
    310310        return handler 
     311 
     312 
     313def XMLRPCDispatcher(next_dispatcher=Dispatcher()): 
     314    from cherrypy.lib import xmlrpc 
     315    def xmlrpc_dispatch(path_info): 
     316        path_info = xmlrpc.patched_path(path_info) 
     317        return next_dispatcher(path_info) 
     318    return xmlrpc_dispatch 
     319 
     320 
     321def VirtualHost(next_dispatcher=Dispatcher(), use_x_forwarded_host=True, **domains): 
     322    """Select a different handler based on the Host header. 
     323     
     324    Useful when running multiple sites within one CP server. 
     325     
     326    From http://groups.google.com/group/cherrypy-users/browse_thread/thread/f393540fe278e54d: 
     327     
     328    For various reasons I need several domains to point to different parts of a 
     329    single website structure as well as to their own "homepage"   EG 
     330     
     331    http://www.mydom1.com  ->  root 
     332    http://www.mydom2.com  ->  root/mydom2/ 
     333    http://www.mydom3.com  ->  root/mydom3/ 
     334    http://www.mydom4.com  ->  under construction page 
     335     
     336    but also to have  http://www.mydom1.com/mydom2/  etc to be valid pages in 
     337    their own right. 
     338    """ 
     339    from cherrypy.lib import http 
     340    def vhost_dispatch(path_info): 
     341        header = cherrypy.request.headers.get 
     342         
     343        domain = header('Host', '') 
     344        if use_x_forwarded_host: 
     345            domain = header("X-Forwarded-Host", domain) 
     346         
     347        prefix = domains.get(domain, "") 
     348        if prefix: 
     349            path_info = http.urljoin(prefix, path_info) 
     350         
     351        return next_dispatcher(path_info) 
     352    return vhost_dispatch 
     353 
  • _cperror.py

    old new  
    1212class InternalRedirect(CherryPyException): 
    1313    """Exception raised to switch to the handler for a different URL. 
    1414     
    15     If you supply a query string, it will replace request.params. 
    16     If you omit the query string (no question mark), the params from the 
    17     original request will remain in effect. 
    18     To erase any query string parameters, write url + "?" with no params. 
     15    Any request.params must be supplied in a query string. 
    1916    """ 
    2017     
    2118    def __init__(self, path): 
  • _cprequest.py

    old new  
    135135class Request(object): 
    136136    """An HTTP request.""" 
    137137     
     138    prev = None 
     139     
    138140    # Conversation/connection attributes 
    139141    local = http.Host("localhost", 80) 
    140142    remote = http.Host("localhost", 1111) 
     
    276278            # path_info should be the path from the 
    277279            # app root (script_name) to the handler. 
    278280            self.script_name = self.app.script_name 
    279             self.path_info = path[len(self.script_name.rstrip("/")):] 
     281            self.path_info = pi = path[len(self.script_name.rstrip("/")):] 
    280282             
    281             # Loop to allow for InternalRedirect. 
    282             pi = self.path_info 
    283             qs = self.query_string 
    284             while True: 
    285                 try: 
    286                     self.respond(pi) 
    287                     break 
    288                 except cherrypy.InternalRedirect, ir: 
    289                     if (ir.path in self.redirections 
    290                         and not self.recursive_redirect): 
    291                         raise RuntimeError("InternalRedirect visited the " 
    292                                            "same URL twice: %s" % repr(ir.path)) 
    293                      
    294                     # Add the *previous* path_info + qs to self.redirections. 
    295                     if qs: 
    296                         qs = "?" + qs 
    297                     self.redirections.append(pi + qs) 
    298                      
    299                     pi = self.path_info = ir.path 
    300                     qs = self.query_string = ir.query_string 
    301                     if qs: 
    302                         self.params = http.parse_query_string(qs) 
    303         except (KeyboardInterrupt, SystemExit): 
     283            self.respond(pi) 
     284             
     285        except (KeyboardInterrupt, SystemExit, cherrypy.InternalRedirect): 
    304286            raise 
    305287        except: 
    306288            if self.throw_errors: 
     
    383365            self.handle_error(sys.exc_info()) 
    384366     
    385367    def process_headers(self): 
    386         # Guard against re-reading body (e.g. on InternalRedirect) 
    387         if self.headers_read: 
    388             return 
    389         self.headers_read = True 
    390          
    391368        self.params = http.parse_query_string(self.query_string) 
    392369         
    393370        # Process the headers into self.headers 
     
    451428     
    452429    def process_body(self): 
    453430        """Convert request.rfile into request.params (or request.body).""" 
    454         # Guard against re-reading body (e.g. on InternalRedirect) 
    455         if self.body_read: 
    456             return 
    457         self.body_read = True 
    458          
    459431        # FieldStorage only recognizes POST, so fake it. 
    460432        methenv = {'REQUEST_METHOD': "POST"} 
    461433        try: 
  • _cptools.py

    old new  
    214214    index = __call__ 
    215215 
    216216 
    217 class XMLRPCTool(object): 
    218     """Tool for using XMLRPC over HTTP. 
    219      
    220     Python's None value cannot be used in standard XML-RPC; to allow 
    221     using it via an extension, provide a true value for allow_none. 
    222     """ 
    223      
    224     def _setup(self): 
    225         """Hook this tool into cherrypy.request.""" 
    226         request = cherrypy.request 
    227          
    228         # Guard against running this method twice. 
    229         if hasattr(request, 'xmlrpc'): 
    230             return 
    231         request.xmlrpc = True 
    232          
    233         request.error_response = _xmlrpc.on_error 
    234         path_info = request.path_info 
    235         ppath = _xmlrpc.patched_path(path_info) 
    236         if ppath != path_info: 
    237             raise cherrypy.InternalRedirect(ppath) 
    238  
    239  
    240217class WSGIAppTool(HandlerTool): 
    241218    """A tool for running any WSGI middleware/application within CP. 
    242219     
     
    332309_d.session_auth = SessionAuthTool(cptools.session_auth) 
    333310_d.proxy = Tool('before_request_body', cptools.proxy, priority=30) 
    334311_d.response_headers = Tool('on_start_resource', cptools.response_headers) 
    335 _d.virtual_host = Tool('on_start_resource', cptools.virtual_host, priority=40) 
    336312_d.log_tracebacks = Tool('before_error_response', cptools.log_traceback) 
    337313_d.log_headers = Tool('before_error_response', cptools.log_request_headers) 
    338314_d.err_redirect = ErrorTool(cptools.redirect) 
     
    345321_d.staticfile = HandlerTool(static.staticfile) 
    346322# _sessions.init must be bound after headers are read 
    347323_d.sessions = SessionTool('before_request_body', _sessions.init) 
    348 _d.xmlrpc = XMLRPCTool(
     324_d.xmlrpc = ErrorTool(_xmlrpc.on_error
    349325_d.wsgiapp = WSGIAppTool(_wsgiapp.run) 
    350326_d.caching = CachingTool('before_handler', _caching.get, 'caching') 
    351327_d.expires = Tool('before_finalize', _caching.expires) 
  • _cptree.py

    old new  
    11"""CherryPy Application and Tree objects.""" 
    22 
    33import os 
     4import StringIO 
    45import sys 
    56import cherrypy 
    67from cherrypy import _cpconfig, _cplogging, tools 
     
    8687        remote = http.Host(env('REMOTE_ADDR', ''), 
    8788                           int(env('REMOTE_PORT', -1)), 
    8889                           env('REMOTE_HOST', '')) 
    89         request = cherrypy.engine.request(local, remote, 
    90                                           env('wsgi.url_scheme'), 
    91                                           env('ACTUAL_SERVER_PROTOCOL', "HTTP/1.1")) 
    92          
     90        scheme = env('wsgi.url_scheme') 
     91        sproto = env('ACTUAL_SERVER_PROTOCOL', "HTTP/1.1") 
    9392        # LOGON_USER is served by IIS, and is the name of the 
    9493        # user after having been mapped to a local account. 
    9594        # Both IIS and Apache set REMOTE_USER, when possible. 
    96         request.login = env('LOGON_USER') or env('REMOTE_USER') or None 
     95        login = env('LOGON_USER') or env('REMOTE_USER') or None 
    9796         
    98         request.multithread = environ['wsgi.multithread'] 
    99         request.multiprocess = environ['wsgi.multiprocess'] 
    100         request.wsgi_environ = environ 
     97        meth = environ['REQUEST_METHOD'] 
     98        path = env('SCRIPT_NAME', '') + env('PATH_INFO', '') 
     99        qs = env('QUERY_STRING', '') 
     100        rproto = env('SERVER_PROTOCOL') 
     101        headers = list(translate_headers(environ)) 
     102        rfile = environ['wsgi.input'] 
    101103         
    102         request.app = app 
     104        # Loop to allow for InternalRedirect. 
     105        prev = None 
     106        redirections = [] 
     107        while True: 
     108            try: 
     109                request = cherrypy.engine.request(local, remote, scheme, sproto) 
     110                request.login = login 
     111                request.multithread = environ['wsgi.multithread'] 
     112                request.multiprocess = environ['wsgi.multiprocess'] 
     113                request.wsgi_environ = environ 
     114                request.app = app 
     115                if prev: 
     116                    request.prev = prev 
     117                response = request.run(meth, path, qs, rproto, headers, rfile) 
     118                break 
     119            except cherrypy.InternalRedirect, ir: 
     120                request.close() 
     121                prev = request 
     122                 
     123                if (ir.path in redirections and not self.recursive_redirect): 
     124                    raise RuntimeError("InternalRedirect visited the " 
     125                                       "same URL twice: %s" % repr(ir.path)) 
     126                else: 
     127                    # Add the *previous* path_info + qs to redirections. 
     128                    if qs: 
     129                        qs = "?" + qs 
     130                    redirections.append(path + qs) 
     131                 
     132                # Munge arguments to request.run and try again. 
     133                meth = "GET" 
     134                path = ir.path 
     135                qs = ir.query_string 
     136                rfile = StringIO.StringIO() 
    103137         
    104         path = env('SCRIPT_NAME', '') + env('PATH_INFO', '') 
    105         response = request.run(environ['REQUEST_METHOD'], path, 
    106                                env('QUERY_STRING', ''), 
    107                                env('SERVER_PROTOCOL'), 
    108                                translate_headers(environ), 
    109                                environ['wsgi.input']) 
    110138        s, h, b = response.status, response.header_list, response.body 
    111139        exc = None 
    112140    except (KeyboardInterrupt, SystemExit), ex: 
  • lib/cptools.py

    old new  
    272272                 for k in dir(SessionAuth) if not k.startswith("__")]) 
    273273 
    274274 
    275 def virtual_host(use_x_forwarded_host=True, **domains): 
    276     """Redirect internally based on the Host header. 
    277      
    278     Useful when running multiple sites within one CP server. 
    279      
    280     From http://groups.google.com/group/cherrypy-users/browse_thread/thread/f393540fe278e54d: 
    281      
    282     For various reasons I need several domains to point to different parts of a 
    283     single website structure as well as to their own "homepage"   EG 
    284      
    285     http://www.mydom1.com  ->  root 
    286     http://www.mydom2.com  ->  root/mydom2/ 
    287     http://www.mydom3.com  ->  root/mydom3/ 
    288     http://www.mydom4.com  ->  under construction page 
    289      
    290     but also to have  http://www.mydom1.com/mydom2/  etc to be valid pages in 
    291     their own right. 
    292     """ 
    293     request = cherrypy.request 
    294      
    295     # Guard against running twice. 
    296     if hasattr(request, "virtual_prefix"): 
    297         return 
    298      
    299     domain = request.headers.get('Host', '') 
    300     if use_x_forwarded_host: 
    301         domain = request.headers.get("X-Forwarded-Host", domain) 
    302      
    303     request.virtual_prefix = prefix = domains.get(domain, "") 
    304     if prefix: 
    305         raise cherrypy.InternalRedirect(_http.urljoin(prefix, request.path_info)) 
    306  
    307275def log_traceback(): 
    308276    """Write the last error's traceback to the cherrypy error log.""" 
    309277    from cherrypy import _cperror 
  • test/test_core.py

    old new  
    164164            raise cherrypy.InternalRedirect("cousin?t=6") 
    165165         
    166166        def cousin(self, t): 
    167             return repr(cherrypy.request.redirections + 
    168                         [cherrypy.url(qs=cherrypy.request.query_string)]) 
     167            assert cherrypy.request.prev.closed 
     168            return cherrypy.request.prev.query_string 
    169169         
    170170        def petshop(self, user_id): 
    171171            if user_id == "parrot": 
     
    173173                raise cherrypy.InternalRedirect('/image/getImagesByUser?user_id=slug') 
    174174            elif user_id == "terrier": 
    175175                # Trade it for a fish when redirecting 
    176                 cherrypy.request.params = {"user_id": "fish"} 
    177                 raise cherrypy.InternalRedirect('/image/getImagesByUser') 
     176                raise cherrypy.InternalRedirect('/image/getImagesByUser?user_id=fish') 
    178177            else: 
    179178                # This should pass the user_id through to getImagesByUser 
    180                 raise cherrypy.InternalRedirect('/image/getImagesByUser'
     179                raise cherrypy.InternalRedirect('/image/getImagesByUser?user_id=%s' % user_id
    181180         
    182181        # We support Python 2.3, but the @-deco syntax would look like this: 
    183182        # @tools.login_redir() 
     
    606605        self.assertStatus(200) 
    607606         
    608607        # Relative path in InternalRedirect. 
    609         # Also tests request.redirections 
     608        # Also tests request.prev. 
    610609        self.getPage("/internalredirect/relative?a=3&b=5") 
    611         self.assertBody("['/internalredirect/relative?a=3&b=5', " 
    612                         "'%s/internalredirect/cousin?t=6']" % self.base()) 
     610        self.assertBody("a=3&b=5") 
    613611        self.assertStatus(200) 
    614612         
    615613        # InternalRedirect on error 
  • test/test_virtualhost.py

    old new  
    33test.prefer_parent_path() 
    44 
    55import cherrypy 
     6from cherrypy import _cpdispatch 
    67 
    78def setup_server(): 
    89    class Root: 
     
    3839    root = Root() 
    3940    root.mydom2 = VHost("Domain 2") 
    4041    root.mydom3 = VHost("Domain 3") 
    41     cherrypy.tree.mount(root) 
     42    cherrypy.tree.mount(root, config={'/': { 
     43        'request.dispatch': _cpdispatch.VirtualHost( 
     44            **{'www.mydom2.com': '/mydom2', 
     45               'www.mydom3.com': '/mydom3', 
     46               'www.mydom4.com': '/dom4', 
     47               }), 
     48        }}) 
    4249     
    43     cherrypy.config.update({ 
    44         'environment': 'test_suite', 
    45         'tools.virtual_host.on': True, 
    46         'tools.virtual_host.www.mydom2.com': '/mydom2', 
    47         'tools.virtual_host.www.mydom3.com': '/mydom3', 
    48         'tools.virtual_host.www.mydom4.com': '/dom4', 
    49         }) 
     50    cherrypy.config.update({'environment': 'test_suite'}) 
    5051 
    5152from cherrypy.test import helper 
    5253 
     
    7677        self.getPage("/vmethod/pos", [('Host', 'www.mydom3.com')]) 
    7778        self.assertBody("You sent 'pos'") 
    7879         
     80        # Test that cherrypy.url uses the browser url, not the virtual url 
    7981        self.getPage("/url", [('Host', 'www.mydom2.com')]) 
    8082        self.assertBody("http://www.mydom2.com/nextpage") 
    8183 
  • test/test_xmlrpc.py

    old new  
    22test.prefer_parent_path() 
    33import xmlrpclib 
    44 
     5from cherrypy import _cpdispatch 
    56 
     7 
    68def setup_server(): 
    79    import cherrypy 
    810    from cherrypy import _cptools 
     
    5759 
    5860    root = Root() 
    5961    root.xmlrpc = XmlRpc() 
    60     cherrypy.tree.mount(root) 
     62    cherrypy.tree.mount(root, config={'/': { 
     63        'request.dispatch': _cpdispatch.XMLRPCDispatcher(), 
     64        }}) 
    6165    cherrypy.config.update({'environment': 'test_suite'}) 
    6266 
    6367 

Hosted by WebFaction

Log in as guest/cpguest to create tickets