bigywater.tech
Django · 21

HttpResponse、JsonResponse 与响应头

视图返回的 HttpResponse 到底带哪些头?JsonResponse 会怎么序列化 datetime、Decimal?头部能不能被注入换行?这篇不看文档,把这些行为一条条试出来。

BadHeaderError
响应头的值里带 \r\n 会被拒绝,不能借此注入 Set-Cookie
safe=False
JsonResponse 传列表必须 safe=False;datetime / Decimal / UUID 会被编码成字符串
Content-Length
不带 CommonMiddleware 时响应里没有 Content-Length

默认响应头

实测 · 本机执行输出
status 200
  Content-Type: text/html; charset=utf-8
  Content-Length: 5
charset = utf-8

视图只返回 HttpResponse('hello'),得到的 Content-Type 带 charset。Content-Length 不是 HttpResponse 自己算的(见第五节)。

响应头与 Cookie

实测 · 本机执行输出
{'Content-Type': 'text/html; charset=utf-8', 'x-custom': 'b', 'X-Other': '1', 'Content-Length': '1'}
r['X-Custom'] = b  r['x-CUSTOM'] = b
Set-Cookie: Set-Cookie: sid=abc; expires=Wed, 30 Sep 2026 12:00:43 GMT; HttpOnly; Max-Age=60; Path=/; SameSite=Lax
has_header("x-other") = True

response.headers 是大小写不敏感的字典;重复赋值以最后一次为准。Cookie 通过 set_cookie 写入 Set-Cookie 头,可以直接指定 httponly、samesite、max_age。

JsonResponse

实测 · 本机执行输出
Content-Type: application/json
body: {"when": "2026-01-02T03:04:05", "price": "9.90", "id": "00000000-0000-0000-0000-000000000001"}
safe=False 的列表: [1, 2, 3]
JsonResponse([1,2]) → TypeError: In order to allow non-dict objects to be serialized set the safe parameter to False.
JsonResponse({set}) → TypeError: Object of type set is not JSON serializable

默认序列化器是 DjangoJSONEncoder,认识 datetime、Decimal、UUID 等;它不认识 set。safe=True(默认)只允许 dict 作为顶层,列表要显式 safe=False——这是历史上防 JSON 劫持的保守选择(这一条来自文档说法,本文没有验证其安全性)。

头部注入

实测 · 本机执行输出
BadHeaderError: Header values can't contain newlines (got 'a\r\nSet-Cookie: pwned=1')

值里带换行会立刻抛 BadHeaderError,而不是等到发送时。

Content-Length

实测 · 本机执行输出
无中间件: {'Content-Type': 'text/html; charset=utf-8'}

响应阶段由 CommonMiddleware 加上。流式响应没有它(第 22 篇)。

分步演示:响应头

HttpResponse
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Python 3.14.7 / Django 6.1.1(默认用 SQLite,其它数据库会在文中注明),用 django.test.Client 或真实的本机服务器进程实测;计时用 time.perf_counter,数字每次运行会有小幅抖动。用 django.test.Client 读取响应
    • 没有验证:真实 WSGI 服务器对头部的二次处理、GZipMiddleware 对 Content-Length 的影响、Cookie 的 secure / domain 属性、headers 里非 ASCII 值的编码
    京ICP备2026067502号-1京公网安备11010502063487号