Django 3.1中如何移除TemplateResponse返回的Server响应头
问题原因
两个现象的核心原因如下:
- 响应对象里找不到
Server头,是因为Django框架本身默认不会添加该响应头。这个头是请求链路中Django上游组件注入的:Django处理完请求返回响应后,上游组件才会追加这个头发给客户端,常见的添加来源包括:- 本地开发用的
runserver内置WSGI服务器 - 生产部署用的WSGI/ASGI服务:Gunicorn、uWSGI、Daphne等
- 反向代理层:Nginx、Apache、Caddy等
- 本地开发用的
- 中间件抛出
ValueError: too many values to unpack,是因为直接操作了Django的私有属性_headers。这个字典的存储格式是小写头名: (标准头名, 头值)的二元元组结构,直接赋值为字符串"Empty"后,后续框架读取时会尝试解包出两个元素,字符串作为可迭代对象会逐字符拆分,自然触发长度不匹配的错误。
正确解决方案
Server头由上游组件追加,仅在Django层操作无法彻底移除,需要根据部署链路对应配置:
1. 开发环境(runserver启动)
Django内置开发服务器默认会返回带Python、WSGI版本的Server头,在项目settings.py最顶部添加如下代码即可移除:
from wsgiref.simple_server import WSGIServer WSGIServer.server_version = ""
如果需要自定义Server头内容,直接给server_version赋值对应字符串即可。
2. 生产环境使用WSGI/ASGI服务
- 用Gunicorn启动服务时,在Gunicorn配置文件中添加如下配置即可移除默认Server头:
# gunicorn.conf.py server_software = "" - 用uWSGI启动服务时,在uWSGI配置文件中添加
http-server-name = ""即可。
3. 前端挂有反向代理的场景
如果服务前部署了Nginx、Apache这类反向代理,需要在代理层配置移除头:
- Nginx配置:
在http或对应站点的server块中添加server_tokens off;可以隐藏Nginx版本号,但仍会返回Server: nginx;如果需要完全移除头,加载ngx_headers_more模块后添加配置:more_clear_headers Server; - Apache配置:
先添加ServerTokens Prod、ServerSignature Off隐藏版本信息,加载mod_headers模块后添加:Header unset Server
补充:Django层操作响应头的正确写法
不要直接操作_headers这个私有属性,不同Django版本的内部实现可能变动,应该使用Django提供的公开API设置响应头:
class NoServerHeaderMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) # 设置响应头 response["Server"] = "your_custom_value" # 删除响应头用 del response["Server"] return response
注意:如果上游服务会强制覆盖Server头,Django层的设置会被覆盖,必须优先在上游组件配置修改。
内容的提问来源于stack exchange,提问作者Enrique Uzcategui
相关产品推荐
相关产品推荐

