You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask子域名转发脚本无法正确传递上传文件问题排查

问题解决:Flask子域名转发时文件上传与请求头保留兼容方案

问题根源

转发multipart/form-data类型的POST请求时,直接传递原请求的所有头会引发冲突:原请求的Content-Length和带boundary的Content-Type会被带到转发请求中,但requests库在处理files和data参数时会自动生成新的Content-Type(包含正确的boundary)和Content-Length,两者冲突导致目标Flask服务无法正确解析表单数据,最终request.files为空。

解决方案

复制原请求头后,移除会引发冲突的Content-Length和Content-Type,让requests库自动处理这两个头,同时保留其他关键头(如Cookie、Cf-Connecting-Ip、X-Forwarded-For等)。

修改后的转发代码

from flask import Flask, request, render_template, Response
import requests

app = Flask(__name__, template_folder='../templates')


@app.route('/', defaults={'path': ''}, methods=['GET', 'POST'])
@app.route('/<path:path>', methods=['GET', 'POST'])
def index(path):
    headers = dict(request.headers)  # 复制原请求头为可变字典
    subdomain = headers['Host'].replace("mydomain.com", "")

    port_mapping = {
        '': 5001,
        'test.': 5002
    }

    if subdomain in port_mapping:
        new_port = port_mapping[subdomain]
        destination_url = f'http://127.0.0.1:{new_port}'

        if request.method == 'POST':
            # 移除冲突头,让requests自动生成正确的multipart头信息
            headers.pop('Content-Length', None)
            headers.pop('Content-Type', None)
            
            response = requests.post(
                destination_url + request.full_path,
                headers=headers,
                data=request.form,
                files=request.files
            )
        else:
            response = requests.get(
                destination_url + request.full_path,
                headers=headers
            )

        return Response(response.content, status=response.status_code, headers=dict(response.headers))
    else:
        return render_template("/errors/subdomain_not_found.html")


if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5000, debug=True)

关键修改说明

  • headers = dict(request.headers):将原请求头转换为可变字典,便于修改操作
  • headers.pop('Content-Length', None)和headers.pop('Content-Type', None):安全移除会与requests自动生成的头冲突的字段,避免解析错误
  • 保留所有其他请求头,确保Session(Cookie)、客户端IP(Cf-Connecting-Ip、X-Forwarded-For)等关键信息正常传递

验证方式

  1. 通过子域名访问上传页面,上传文件后,目标服务(5002端口)的request.files应能正确获取到文件对象
  2. 检查目标服务的request.cookies是否包含原Session值,request.headers.get('Cf-Connecting-Ip')是否正确获取客户端IP

内容的提问来源于stack exchange,提问作者ward franssen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 02:12:45