bigywater.tech
Flask · 32

Query String 参数解析

?k=1&k=2 能拿到几个??k 和 ?k= 一样吗?转换失败会怎样?参数多到什么程度会被拒?这篇把查询字符串的各种边界都跑一遍。

4094
gunicorn 默认的请求行上限(字节),超过得到 400
3
同一个键 k=1&k=2&k=3 出现的值个数(get 取第一个,getlist 取全部)
BadRequestKeyError
args["缺失的键"] 抛出的异常(默认变成 400)

MultiDict

实测 · 本机执行输出
  ?k=1&k=2&k=3 → {'args': {'k': ['1', '2', '3']}, 'first': '1', 'getlist': ['1', '2', '3'], 'raw': 'k=1&k=2&k=3'}
  类型: ImmutableMultiDict | 修改会怎样: TypeError: 'ImmutableMultiDict' objects are immutable

上一篇:Werkzeug Request 对象;下一篇:Form Data 与 JSON Body。

边界写法

实测 · 本机执行输出
  ?k=             → {'k': ['']}
  ?k              → {'k': ['']}
  ?k=&k=1         → {'k': ['', '1']}
  ?&&k=1&&        → {'k': ['1']}
  ?=v             → {'': ['v']}
  ?a=1&a          → {'a': ['1', '']}
  ?k=a%26b        → {'k': ['a&b']}
  ?k=a+b          → {'k': ['a b']}
  ?k=%E4%B8%AD    → {'k': ['中']}
  ?k=1;j=2        → {'k': ['1;j=2']}
  ?k[]=1&k[]=2    → {'k[]': ['1', '2']}
  ?k=a=b          → {'k': ['a=b']}

类型转换

实测 · 本机执行输出
  get("n", type=int)         → 12
  get("bad", type=int)       → None
  get("bad", 0, type=int)    → 0
  get("neg", type=int)       → -3
  get("f", type=float)       → 1.5
  get("empty", type=int)     → None
  get("missing")             → None
  get("missing", "x")        → 'x'
  a["n"]                     → '12'
  a["missing"] → BadRequestKeyError (KeyError 的子类,默认变成 400): BadRequest
  视图里直接 request.args["must"] 缺失 → 400

数量与长度限制

实测 · 本机执行输出
  test client 发 5000 个查询参数 → 200 | 解析出 5000 个
  gunicorn 默认:100 个参数(查询串 589 字节)→ 200 '100'
  gunicorn 默认:1000 个参数(查询串 6889 字节)→ 400 '<html>\n  <head>\n    <title>Bad Request</'
  gunicorn 默认:1500 个参数(查询串 10889 字节)→ 400 '<html>\n  <head>\n    <title>Bad Request</'
  gunicorn 默认的请求行上限 limit_request_line = 4094 字节(超过返回 4xx)

args 与 values

实测 · 本机执行输出
  args: {'k': 'from_args'} | form: {'k': 'from_form', 'only_form': '1'} | values: {'k': ['from_args', 'from_form'], 'only_form': ['1']}

分步演示

查询字符串
本步的对象

    本文用到的工具与边界

    • 本机 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,数字每次运行会有小幅抖动
    • 没有验证:uWSGI 与 Nginx 对请求行长度的限制(见第 173、174 篇)、查询串里的非 UTF-8 编码(见第 30 篇)、Werkzeug 对超大查询串的内存消耗、flask 3.1 里 args 的 parameter_storage_class 自定义
    京ICP备2026067502号-1京公网安备11010502063487号