改进 Twisted 代理服务器以根据 URL 灵活选择后端服务器

84 阅读2分钟

我们尝试使用 Twisted.Web 框架创建代理服务器。该代理服务器应该根据请求中的 URL 将请求转发到两台不同的服务器之一。我们期望当我们注释掉一行代码并取消注释另一行代码时,请求能够被正确地代理到相应的服务器,但是事实并非如此。

huake_00257_.jpg 以下是我们的代码:

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()

当我们运行此脚本并导航至服务器 "localhost:8080/ANYTHING_AT_ALL" 时,我们得到了 "Method Not Allowed" 错误。这说明我们的代理服务器没有正确转发请求。

2、解决方案

出现了两个解决方案:

解决方案 1:

我们注意到在 Simple 类中,isLeaf 变量被设置为 True,这意味着这是一个叶节点。但是,我们却在 getChild() 方法中实现了子节点的处理逻辑,这显然不合理。

因此,我们需要将 isLeaf 变量设置为 False,这样 Simple 类就会被识别为非叶节点,getChild() 方法才会被调用,并根据请求的 URL 将请求正确地转发到相应的服务器。

代码如下:

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()

解决方案 2:

另一个解决方案是将代理服务器的路径设置为 "/"+name,这样才能正确地将请求转发到相应的服务器。

代码如下:

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()

经过以上修改,代理服务器就可以根据 URL 将请求正确地转发到相应的服务器了。