Python3 Twisted反向代理重定向异常,请求技术协助
问题分析与解决
你的问题根源在于两点:
- 目标站点(YouTube/Yahoo)强制使用HTTPS,但你的代理默认连接80端口(HTTP),触发站点重定向时浏览器会错误拼接地址;
- Twisted原生
ReverseProxyResource未正确处理重定向的Location头,导致跳转路径混乱。
修正后的代码
from twisted.internet import reactor from twisted.web.server import Site from twisted.web.resource import Resource from twisted.web import proxy class FixedReverseProxyResource(proxy.ReverseProxyResource): def getChild(self, path, request): # 正确拼接子资源路径,保留代理前缀 return FixedReverseProxyResource( self.host, self.port, self.path + b'/' + path, self.secure, self.reactor ) def render(self, request): # 传递正确的Host头,避免目标站点返回错误重定向 request.requestHeaders.setRawHeaders(b'host', [self.host.encode('utf-8')]) return super().render(request) def proxyFactory(self, *args, **kwargs): factory = super().proxyFactory(*args, **kwargs) # 重写重定向处理,修正Location头 original_handle_end = factory.handleResponseEnd def handle_response_end(): if factory.response_headers.hasHeader(b'location'): locations = factory.response_headers.getRawHeaders(b'location') corrected_locations = [] target_host = self.host.encode('utf-8') proxy_prefix = b'/app1' if self.host == 'youtube.com' else b'/app2' local_proxy = b'http://127.0.0.1:8090' + proxy_prefix for loc in locations: if loc.startswith(b'https://' + target_host): # 替换目标域名为本地代理地址 path = loc[len(b'https://' + target_host):] corrected_locations.append(local_proxy + path) else: corrected_locations.append(loc) factory.response_headers.setRawHeaders(b'location', corrected_locations) original_handle_end() factory.handleResponseEnd = handle_response_end return factory # 连接目标站点的HTTPS端口,开启secure模式 site1 = FixedReverseProxyResource('youtube.com', 443, b'', secure=True) site2 = FixedReverseProxyResource('yahoo.com', 443, b'', secure=True) root = Resource() root.putChild(b"app1", site1) root.putChild(b"app2", site2) reactor.listenTCP(8090, Site(root)) reactor.run()
关键修改说明
- 切换到HTTPS端口:目标站点均强制HTTPS,因此代理需连接443端口并设置
secure=True,避免初始HTTP请求触发错误重定向; - 修正重定向路径:自定义代理资源类,重写
proxyFactory方法修改Location头,将目标站点的域名替换为本地代理的地址和前缀(如https://youtube.com/watch转为http://127.0.0.1:8090/app1/watch); - 传递正确Host头:确保请求发送到目标站点时,Host头为目标域名而非本地代理地址,避免站点拒绝请求或返回错误跳转。
额外提示
部分站点存在反代理机制,可能需要在render方法中添加模拟浏览器的请求头(如User-Agent),才能正常访问。
内容的提问来源于stack exchange,提问作者xelab04
相关产品推荐
相关产品推荐

