bigywater.tech
Flask · 103

请求参数校验

拿到请求参数之后,Flask 自己替你检查了什么?type=int 失败会怎样?JSON 里缺字段会返回什么?这篇用 test_client 把各种边界输入的结果逐个打印出来。

不报错 ≠ 合法
args.get(type=int) 失败时回退默认值,而 ' 12 '、'1_000'、Unicode 数字都被接受
500
request.json["name"] 缺键与请求体是列表时的状态码(不是 400)
413
请求体超过 MAX_CONTENT_LENGTH 时的状态码

type=int 的行为

实测 · 本机执行输出
  n='12'                     → {'n': 12}
  n='abc'                    → {'n': 'DEFAULT'}
  n='12abc'                  → {'n': 'DEFAULT'}
  n=' 12 '                   → {'n': 12}
  n='1_000'                  → {'n': 1000}
  n='+5'                     → {'n': 5}
  n='-5'                     → {'n': -5}
  n='١٢'                     → {'n': 12}
  n='99999999999999999999'   → {'n': 99999999999999999999}
  n=''                       → {'n': 'DEFAULT'}
  n='1.5'                    → {'n': 'DEFAULT'}
  没有传 n → {'n': 'DEFAULT'}

上一篇:API 错误响应统一格式;下一篇:API 分页。

float 与 bool

实测 · 本机执行输出
  x='1.5'    → {'repr': '1.5'}
  x='nan'    → {'repr': 'nan'}
  x='inf'    → {'repr': 'inf'}
  x='-inf'   → {'repr': '-inf'}
  x='1e400'  → {'repr': 'inf'}
  x='abc'    → {'repr': 'None'}
  flag='true'   → {'flag': True}
  flag='false'  → {'flag': True}
  flag='0'      → {'flag': True}
  flag='1'      → {'flag': True}
  flag=''       → {'flag': False}

路径转换器

实测 · 本机执行输出
  /items/5     → 200 {'i': 5}
  /items/007   → 200 {'i': 7}
  /items/abc   → 404 
  /items/-1    → 404 
  /items/1.5   → 404 
  /items/٣     → 200 {'i': 3}

JSON 请求体

实测 · 本机执行输出
  缺 name(KeyError)→ 500 <!doctype html> <html lang=en> <title>500 Internal Server Er
  name 是整数 12345 → 200 {'name': 12345}
  name 是嵌套对象 → 200 {'name': {'a': [1, 2]}}
  请求体是列表 → 500 ( <!doctype html> <html lang=en> <title>500 Internal )

手写校验

实测 · 本机执行输出
  合法                 → 201 {'ok': True, 'user': {'age': 30, 'name': 'ann'}}
  name 缺失、age 越界     → 422 {'errors': {'age': '必填,0-150 的整数', 'name': '必填,字符串,1-20 个字符'}}
  age 是字符串           → 422 {'errors': {'age': '必填,0-150 的整数'}}
  age 是 true         → 422 {'errors': {'age': '必填,0-150 的整数'}}
  请求体是列表             → 422 {'errors': {'_': '请求体必须是 JSON 对象'}}
  非法 JSON(silent=True 之后当成 None)→ 422 {'errors': {'_': '请求体必须是 JSON 对象'}}

第 115、116 篇会用 Marshmallow 与 Pydantic 做同样的事。

分页参数

实测 · 本机执行输出
  /page                       → {'limit': 20, 'offset': 0}
  /page?limit=5&offset=10     → {'limit': 5, 'offset': 10}
  /page?limit=0               → {'limit': 1, 'offset': 0}
  /page?limit=100000          → {'limit': 100, 'offset': 0}
  /page?limit=-3&offset=-9    → {'limit': 1, 'offset': 0}
  /page?limit=abc             → {'limit': 20, 'offset': 0}
  getlist:?id=1&id=2&id=x&id=3 → {'ids': [1, 2, 3]} (无法转换的元素被悄悄丢掉)

请求体大小

实测 · 本机执行输出
  请求体 500 字节 → 200
  请求体 1000 字节 → 200
  请求体 1001 字节 → 413
  请求体 5000 字节 → 413

分步演示

请求参数校验
本步的对象

    本文用到的工具与边界

    • 本机 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,数字每次运行会有小幅抖动
    • 没有验证:Marshmallow、Pydantic、webargs 等库的校验(见第 115、116 篇)、multipart 表单与文件上传的校验、MAX_FORM_MEMORY_SIZE 与 MAX_FORM_PARTS 配置、真实 HTTP 下 Content-Length 缺失(分块上传)时的 MAX_CONTENT_LENGTH 行为
    京ICP备2026067502号-1京公网安备11010502063487号