1

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.

Cristian
  • 495
  • 2
  • 9
  • 35
  • are the css by anyway loaded through AJAX calls (XMLHttpRequest ?. if it is the case then mostly your issue is related to CORS and you just need to add the proxied domain to the allow origin on your original site – Hani Jun 20 '16 at 17:43

2 Answers2

1

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>
rrauenza
  • 6,285
  • 4
  • 32
  • 57
  • Yeah, that makes a lot of sense, but I'm trying this and the CSS (and any other links) is still not working. – Cristian Jun 20 '16 at 01:35
  • What kind of errors are you getting? 404 on the CSS? – rrauenza Jun 20 '16 at 01:37
  • Does the code seem to be accurately mapping the source URL to the destination URL? It would be helpful to isolate the mapping versus the proxy. – rrauenza Jun 20 '16 at 01:50
  • Yeah, you're asking if the code on the site works fine without the proxy? yeah it works great, If I were to go to the site directly the css would work fine. The website I'm proxying is `grindhouseburgers.com` by the way. – Cristian Jun 20 '16 at 02:24
  • Ok, I'll try testing with that. – rrauenza Jun 20 '16 at 02:55
  • @Cristian Do you have to use klein? Or could you use twisted? – rrauenza Jun 20 '16 at 03:24
0

this will work

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

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

run("MY_IP", 80)

basically branch is argument to @route annotation not the home function

Hani
  • 1,354
  • 10
  • 20