我们尝试使用 Twisted.Web 框架创建代理服务器。该代理服务器应该根据请求中的 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()
当我们运行此脚本并导航至服务器 "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 将请求正确地转发到相应的服务器了。