Search code examples
pythonpython-3.xtwistedklein-mvc

klein script CSS isn't working


I have a very simple klein script that is just a reverse-proxy:

from klein import run, route, Klein
from twisted.web.proxy import ReverseProxyResource

@route('/')
def home(request, branch=True):
    return ReverseProxyResource('www.example.com', 80, ''.encode('utf-8'))

run("MY_IP", 80)

The only problem is the CSS doesn't work when the website is calling it using relative paths /css/example; I'm not sure how to fix this. I'm open to any suggestions.

I'm using Python-3.3.


Solution

  • This first block of code based on yours was my first pass, but it doesn't work.

    It appeared to work for things like GET /a, but that's because /<path> doesn't include additional /'s. So anything that is deeper than one level won't get proxied.

    Looking into @route, it uses werkzeug underneath which doesn't appear to allow arbitrary wildcards:

    from klein import run
    from klein import route
    from twisted.web.proxy import ReverseProxyResource
    
    @route('/', defaults={'path': ''})
    @route('/<path>')
    def home(request, path):
        print "request: " + str(request)
        print "path: " + path
        return ReverseProxyResource('localhost', 8001, path.encode('utf-8'))
    
    run("localhost", 8000)
    

    If you drop down into twisted, though, you can simply do this:

    # Copyright (c) Twisted Matrix Laboratories.
    # See LICENSE for details.
    
    """
    This example demonstrates how to run a reverse proxy.
    
    Run this example with:
        $ python reverse-proxy.py
    
    Then visit http://localhost:8000/ in your web browser.
    """
    
    from twisted.internet import reactor
    from twisted.web import proxy, server
    
    site = server.Site(proxy.ReverseProxyResource('www.example.com', 80, ''))
    reactor.listenTCP(8000, site)
    reactor.run()
    

    If you want to catch, log, modify, etc, each request, you can subclass ReverseProxyResource and override render(). Note: you also have to override getChild() due to a bug:

    from twisted.internet import reactor                                            
    from twisted.web import proxy                                                   
    from twisted.web import server                                                  
    from twisted.python.compat import urlquote                                      
    
    class MyReverseProxyResource(proxy.ReverseProxyResource):                       
    
        def __init__(self, host='www.example.com', port=80, path='', reactor=reactor):
            proxy.ReverseProxyResource.__init__(self, host, port, path, reactor)    
    
        def getChild(self, path, request):                                          
            # See https://twistedmatrix.com/trac/ticket/7806                        
            return MyReverseProxyResource(                                          
                self.host, self.port, self.path + b'/' + urlquote(path, safe=b"").encode('utf-8'),
                self.reactor)                                                       
    
        def render(self, request):                                                  
            print request                                                           
            return proxy.ReverseProxyResource.render(self, request)                 
    
    
    p = MyReverseProxyResource()                                                    
    site = server.Site(p)                                                           
    reactor.listenTCP(8000, site)                                                   
    reactor.run()
    

    Output:

    <Request at 0x14e9f38 method=GET uri=/css/all.css?20130620 clientproto=HTTP/1.1>
    <Request at 0x15003b0 method=GET uri=/ clientproto=HTTP/1.1>