![NGINX 301 和 302 提供小型 nginx 文档主体。有什么方法可以消除此行为?](https://linux22.com/image/594229/NGINX%20301%20%E5%92%8C%20302%20%E6%8F%90%E4%BE%9B%E5%B0%8F%E5%9E%8B%20nginx%20%E6%96%87%E6%A1%A3%E4%B8%BB%E4%BD%93%E3%80%82%E6%9C%89%E4%BB%80%E4%B9%88%E6%96%B9%E6%B3%95%E5%8F%AF%E4%BB%A5%E6%B6%88%E9%99%A4%E6%AD%A4%E8%A1%8C%E4%B8%BA%EF%BC%9F.png)
我们注意到,当使用 nginx 内部 301 和 302 处理时,nginx 将提供具有适当 Location: ... 标头的小文档主体。
类似于以下内容(在 html 中):301 重定向 - nginx。
与上述行为类似,还会发送内容类型 text/html 和内容长度标头。
我们做了很多 302 和一些 301 重定向,我们认为上述行为浪费了带宽。
有什么方法可以禁用这种行为吗?
我们想到的一个想法是将 error_page 301 302 设置为一个空文本文件。我们还没有测试过,但我假设即使使用上述方法,content-type 和 content-length (0) 标头也会被发送。
那么,有没有一种干净的方法可以用 nginx 发送“无正文”的 301/302 重定向?
答案1
仔细考虑你的要求,并认真考虑不做。
RFC 2616指定要删除的实体主体应该存在。
10.3.2 301 永久移动
新的永久 URI 应由响应中的 Location 字段提供。除非请求方法是 HEAD,否则响应实体应包含一个简短的超文本注释,其中包含指向新 URI 的超链接。
和...
10.3.3 302 找到
临时 URI 应由响应中的 Location 字段提供。除非请求方法是 HEAD,否则响应实体应包含一个简短的超文本注释,其中包含指向新 URI 的超链接。
在本上下文中,SHOULD 的定义如下:RFC 2119:
这个词,或形容词“推荐”,意味着在特定情况下可能存在忽略特定项目的正当理由,但在选择不同的方案之前,必须理解和仔细权衡其全部含义。
现在您可以在不违反 RFC 的情况下执行此操作,但您应该意识到其全部含义:
- 您做了很多工作,但几乎没有任何好处。我能想到的禁用实体主体的唯一合理原因是为了节省带宽成本,这确实是您提到的原因,但差异如此之小,以至于您甚至不太可能在带宽图上看到差异。
- 极小部分 Web 客户端不会自动遵循 3xx 重定向。在编写 RFC 时,这个比例要大得多,这就是为什么首先要有这个重定向,但仍有一些古老的怪物潜伏在黑暗的卧室和数据中心壁橱的阴影中,有时它们会出来活动。您最有可能看到的是
curl
,它仍然很常用。
这项建议已有所放宽,RFC 7231,它仅仅表示(针对 301 和 302):
服务器的响应负载通常包含一个简短的超文本注释,其中带有指向新 URI 的超链接。
服务器的响应负载通常包含一个简短的超文本注释,其中带有指向不同 URI 的超链接。
答案2
是的你可以绝对地使用 NGINX 来实现!
只需安装一个异常处理程序,又名
error_page
,以对所需响应进行后处理。确保以某种方式进行设置,以防止错误页面修改 HTTP 状态代码,例如,不要使用该=
参数(或使用它来硬编码您想要的任何代码)。确保
return
带有返回状态代码的响应,允许您选择性地设置[text]
,而不是URL
。指定
default_type
,这""
似乎删除了Content-Type
标题
以下是完整代码,也在我的GitHub在StackOverflow.cnst.nginx.conf
存储库:
# cat sf.421976.301-302-redirect-w-no-http-body-text.nginx.conf | sed 's#^#\t#g'
server {
listen 1976;
error_page 301 302 @30x; # keep original HTTP status code w/o `=`
location @30x {
default_type ""; # will remove Content-Type completely
# `300` is a filler: client will get the original HTTP status code
return 300;
}
return 301 http://example.su/test;
}
以下是其正常工作的确认:
% curl -i localhost:1976 | sed 's#^#\t#g'
HTTP/1.1 301 Moved Permanently
Server: nginx/1.2.1
Date: Mon, 28 Aug 2017 22:02:41 GMT
Content-Length: 0
Connection: keep-alive
Location: http://example.su/test
%
我已经在浏览器中尝试过它,并且它也运行良好。
PS 另一个选择是修改源代码,并编辑ngx_http_error_301_page
等变量,但为什么要走这条艰难的路线呢?!^_^
答案3
这有点丑陋,但也许你可以代理 301/302 请求并使用 proxy_method 将 GET 更改为 HEAD 请求。我还没有测试过,但 head 请求应该只发送没有响应的标头或(希望)content-* 标头。