使用Twisted和Python创建路由器

0 投票
1 回答
1034 浏览
提问于 2025-04-18 13:38

当一个客户端(比如说网页浏览器)访问 localhost:8080 时,它的请求应该被发送到一个由 SERVER_ADDR 定义的地址,比如 http://www.yahoo.com。这更像是一个路由器或负载均衡器,而不是一个代理。

问题:当我的网页浏览器访问 localhost:8080 时,什么都没有返回给它。在Python控制台上,可以看到HTTP请求头已经到达了Twisted应用程序。也许这不能用来重定向浏览器的请求?

from twisted.internet import protocol, reactor

LISTEN_PORT = 8080
SERVER_PORT = 80
SERVER_ADDR = 'http://www.yahoo.com'

class ServerProtocol(protocol.Protocol):
    def __init__(self):
        self.buffer = None
        self.client = None

    def connectionMade(self):
        factory = protocol.ClientFactory()
        factory.protocol = ClientProtocol
        factory.server = self

        reactor.connectTCP(SERVER_ADDR, SERVER_PORT, factory)

    # Client => Proxy
    def dataReceived(self, data):
        print 'Data received from Client:'
        if self.client:
            self.client.write(data)
        else:
            data = data.replace('localhost:8080', SERVER_ADDR)
            print data
            self.buffer = data

    # Proxy => Client
    def write(self, data):
        self.transport.write(data)



class ClientProtocol(protocol.Protocol):
    def connectionMade(self):
        self.factory.server.client = self
        self.write(self.factory.server.buffer)
        self.factory.server.buffer = ''

    # Server => Proxy
    def dataReceived(self, data):
        print 'Data received from Server: '
        print data
        self.factory.server.write(data)

    # Proxy => Server
    def write(self, data):
        if data:
            self.transport.write(data)



def main():
    factory = protocol.ServerFactory()
    factory.protocol = ServerProtocol

    reactor.listenTCP(LISTEN_PORT, factory)
    reactor.run()


if __name__ == '__main__':
    main()

1 个回答

0

对我来说,这个方法部分有效:当我在浏览器中访问 http://localhost:8080 时,Yahoo 服务器给我返回了一个 HTTP 错误 400,表示请求有问题。这是因为你把 GET 请求中的 Host: localhost:8080 替换成了 Host: http://www.yahoo.com,而这里的协议是不对的。正确的写法应该是 Host: www.yahoo.com

不过,这样做之后,它会返回一个 HTTP/1.1 301 Moved Permanently 的重定向,这样你可能会遇到其他问题。

补充一下:你应该去看看 twisted 网站上的代理示例(https://twistedmatrix.com/documents/12.3.0/web/examples/#auto2),深入了解一下它是怎么实现的。

from twisted.web import proxy, http
from twisted.internet import reactor

class ProxyFactory(http.HTTPFactory):
    def buildProtocol(self, addr):
        return proxy.Proxy()

reactor.listenTCP(8080, ProxyFactory())
reactor.run()

撰写回答