bigywater.tech
Flask · 153

test_client() 与真实 HTTP 请求差异

test_client 里测过了,真实服务器上就一定一样吗?哪些行为只有真实 HTTP 才能验证?这篇把同一个应用放在两边,把差异逐项对照出来(包括一个我没预料到的分块上传结果)。

200 而不是 413
分块上传超过 MAX_CONTENT_LENGTH 时,真实服务器的结果(内容被截断到上限)
3 个头
真实服务器比 test client 多出的响应头:connection、date、server
TESTING
决定视图异常是传播给测试还是返回 500 的开关

响应头

实测 · 本机执行输出
  test client: ['content-length', 'content-type']
  gunicorn   : ['connection', 'content-length', 'content-type', 'date', 'server']
  gunicorn 多出: ['connection', 'date', 'server'] | test client 多出: []

上一篇:test_request_context();下一篇:Fixture 与测试应用工厂。

路径解码

实测 · 本机执行输出
  /p/a%2Fb       test client → {'name': 'a/b', 'path': '/p/a/b'}
                 gunicorn     → {'name': 'a/b', 'path': '/p/a/b'}
  /p/a//b        test client → {'name': 'a//b', 'path': '/p/a//b'}
                 gunicorn     → {'name': 'a//b', 'path': '/p/a//b'}
  /p/%E4%B8%AD   test client → {'name': '中', 'path': '/p/中'}
                 gunicorn     → {'name': '中', 'path': '/p/中'}

分块上传与大小限制

实测 · 本机执行输出
  真实 gunicorn,3000 字节分块上传(MAX_CONTENT_LENGTH=1000)→ HTTP/1.1 200 OK | {"cl":null,"n":1000,"te":"chunked"}
  test client,3000 字节(有 Content-Length)→ 413
  test client 里没有直接模拟分块传输的简单写法(data 传迭代器会报 AttributeError),所以分块上传的行为只能用真实服务器验证

第一次运行这一节时我把请求里的换行写错了(写成了字面的反斜杠),得到一个 500,以为是服务器行为,检查输出才发现是我发的请求本身有问题。修正后才看到真实的结果。

异常

实测 · 本机执行输出
  TESTING=True 的 test client → 异常传播到测试代码:RuntimeError: view exploded
  TESTING=False 的 test client → 500
  真实 gunicorn → 500

默认的请求头

实测 · 本机执行输出
  test client: {'host': 'localhost', 'ua': 'Werkzeug/3.1.9', 'url': 'http://localhost/host'}
  真实 http.client: {'host': '127.0.0.1:9601', 'ua': None}

重定向

实测 · 本机执行输出
  test client → 308 http://localhost/dir/
  gunicorn   → 308 http://127.0.0.1:9601/dir/

分步演示

test_client 与真实 HTTP 差异
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.7 / Flask 3.1.3 / Werkzeug 3.1.9 / Jinja2 3.1.6 / SQLAlchemy 2.1.1 / gunicorn 26.2.0(都装在自己的虚拟环境里);大多数实验用 Flask 的 test_client(直接调用 WSGI 应用,不经过网络),需要真实 HTTP 时另起 gunicorn 或开发服务器(端口 9600 以上,本机 127.0.0.1);计时用 time.perf_counter,数字每次运行会有小幅抖动。gunicorn sync worker
    • 没有验证:keep-alive 与 HTTP/1.0 的差异、nginx 在中间时的差异、Expect: 100-continue、非常大的头部、HTTP/2、客户端断开连接时视图的行为
    京ICP备2026067502号-1京公网安备11010502063487号