How do I get my simple twisted proxy to work?

2019-02-18 17:41发布

问题:

I am attempting to make use of the Twisted.Web framework.

Notice the three line comments (#line1, #line2, #line3). I want to create a proxy (gateway?) that will forward a request to one of two servers depending on the url. If I uncomment either comment 1 or 2 (and comment the rest), the request is proxied to the correct server. However, of course, it does not pick the server based on the URL.

from twisted.internet import reactor
from twisted.web import proxy, server
from twisted.web.resource import Resource

class Simple(Resource):
    isLeaf = True
    allowedMethods = ("GET","POST")

    def getChild(self, name, request):
        if name == "/" or name == "":
            return proxy.ReverseProxyResource('localhost', 8086, '')
        else:
            return proxy.ReverseProxyResource('localhost', 8085, '')

simple = Simple()
# site = server.Site(proxy.ReverseProxyResource('localhost', 8085, '')) #line1   
# site = server.Site(proxy.ReverseProxyResource('localhost', 8085, '')) #line2   
site = server.Site(simple)                                              #line3   
reactor.listenTCP(8080, site)
reactor.run()

As the code above currently stands, when I run this script and navigate to server "localhost:8080/ANYTHING_AT_ALL" I get the following response.

Method Not Allowed

Your browser approached me (at /ANYTHING_AT_ALL) with the method "GET". I only allow the methods GET, POST here.

I don't know what I am doing wrong? Any help would be appreciated.

回答1:

Since your Simple class implements the getChild() method, it is implied that this is not a leaf node, however, you are stating that it is a leaf node by setting isLeaf = True. (How can a leaf node have a child?).

Try changing isLeaf = True to isLeaf = False and you'll find that it redirects to the proxy as you'd expect.

From the Resource.getChild docstring:

... This will not be called if the class-level variable 'isLeaf' is set in
    your subclass; instead, the 'postpath' attribute of the request will be
    left as a list of the remaining path elements....


回答2:

Here is the final working solution. Basically two resource request go to the GAE server, and all remaining request go to the GWT server.

Other than implementing mhawke's change, there is only one other change, and that was adding '"/" + name' to the proxy servers path. I assume this had to be done because that portion of the path was consumed and placed in the 'name' variable.

from twisted.internet import reactor
from twisted.web import proxy, server
from twisted.web.resource import Resource

class Simple(Resource):
    isLeaf = False
    allowedMethods = ("GET","POST")
    def getChild(self, name, request):
        print "getChild called with name:'%s'" % name
        if name == "get.json" or name == "post.json":
            print "proxy on GAE"
            return proxy.ReverseProxyResource('localhost', 8085, "/"+name)
        else:
            print "proxy on GWT"
            return proxy.ReverseProxyResource('localhost', 8086, "/"+name)

simple = Simple()
site = server.Site(simple)
reactor.listenTCP(8080, site)
reactor.run()

Thank you.