如何用Python Requests库正确返回HTTP响应(搭建Python反向代理)
解决子路径反向代理托管Flask应用的方案
首先,我猜你是想用middle.py作为反向代理层,把请求转发到helloflask.py的服务上对吧?而且不想占用80/443端口,那咱们可以用Flask配合Werkzeug的工具来实现,或者用更简洁的代理中间件,下面给你两种靠谱的实现方式:
方式一:手动实现Flask反向代理(灵活可控)
先给你的目标Flask应用(helloflask.py)配置子路径支持,不然内部路由会找不到正确的路径:
# helloflask.py from flask import Flask from werkzeug.middleware.proxy_fix import ProxyFix app = Flask(__name__) # 告诉Flask它运行在/myapp子路径下 app.config['APPLICATION_ROOT'] = '/myapp' # 配置ProxyFix,处理反向代理传递的请求头,避免路径识别错误 app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1) @app.route('/') def hello(): return "Hello from Flask app at /myapp!" @app.route('/test') def test(): return "Test route accessible at /myapp/test!" if __name__ == '__main__': # 让Flask仅监听本地指定端口,比如5000 app.run(host='localhost', port=5000)
然后写middle.py作为对外的代理服务器,监听非80/443的端口(比如8080),把/myapp路径的请求转发到本地Flask服务:
# middle.py from flask import Flask, request, Response import requests app = Flask(__name__) # 目标Flask应用的本地地址 TARGET_APP_URL = 'http://localhost:5000' @app.route('/myapp', defaults={'path': ''}) @app.route('/myapp/<path:path>') def proxy_to_flask(path): # 拼接完整的目标请求URL target_url = f"{TARGET_APP_URL}/{path}" # 转发请求的所有信息:方法、数据、请求头(排除Host避免冲突) forwarded_req = requests.request( method=request.method, url=target_url, headers={k: v for k, v in request.headers.items() if k != 'Host'}, data=request.get_data(), cookies=request.cookies, allow_redirects=False ) # 处理响应头,去掉会引发问题的头字段 excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection'] response_headers = [(name, value) for name, value in forwarded_req.raw.headers.items() if name.lower() not in excluded_headers] # 生成响应,同时修正重定向地址(把目标地址替换成子路径) response = Response(forwarded_req.content, forwarded_req.status_code, response_headers) if 'Location' in forwarded_req.headers: old_location = forwarded_req.headers['Location'] response.headers['Location'] = old_location.replace(TARGET_APP_URL, '/myapp') return response if __name__ == '__main__': # 监听所有网卡的8080端口,对外提供服务 app.run(host='0.0.0.0', port=8080)
运行步骤:
- 先启动目标Flask应用:
python helloflask.py - 再启动代理服务器:
python middle.py - 现在就可以通过
http://myserver:8080/myapp访问你的Flask应用,http://myserver:8080/myapp/test访问测试路由
方式二:用Werkzeug ProxyMiddleware简化实现
如果你觉得手动写代理逻辑太麻烦,可以直接用Werkzeug的内置中间件,代码更简洁:
首先确保安装Werkzeug:pip install werkzeug
修改middle.py如下:
# middle.py from werkzeug.middleware.proxy_fix import ProxyFix from werkzeug.middleware.dispatcher import DispatcherMiddleware from flask import Flask # 创建一个空的根应用,处理非/myapp路径的请求 root_app = Flask(__name__) @root_app.route('/') def root_page(): return "This is the root server - visit /myapp to access your Flask app!" # 导入你的目标Flask应用 from helloflask import app as flask_app # 配置路由分发:把/myapp路径的请求转发给flask_app application = DispatcherMiddleware(root_app, { '/myapp': flask_app }) # 加上ProxyFix处理请求头,避免路径识别错误 application = ProxyFix(application, x_for=1, x_proto=1, x_host=1, x_prefix=1) if __name__ == '__main__': from werkzeug.serving import run_simple # 监听0.0.0.0:8080端口 run_simple('0.0.0.0', 8080, application)
注意:helloflask.py的配置要和方式一保持一致(设置APPLICATION_ROOT和ProxyFix)。
关键注意事项
- 必须给目标Flask应用设置
APPLICATION_ROOT,不然它生成的内部URL(比如用url_for生成的链接)会不带子路径,导致跳转错误 - 代理层一定要处理好
Host和Location响应头,不然会出现重定向到错误地址的问题 - 记得在服务器防火墙上开放代理层监听的端口(比如8080),不然外部无法访问
内容的提问来源于stack exchange,提问作者abalter
相关产品推荐
相关产品推荐

