Nginx return 声明不接受 "text"
Nginx return statement not accepting "text"
以下配置对我有用:
server {
listen 80;
root /app/web;
index index.json;
location / {
return 409;
}
}
如果我点击该网站,将显示 409 页面。但是以下不起作用:
server {
listen 80;
root /app/web;
index index.json;
location / {
return 409 "foobar";
}
}
无法访问该页面。但是根据文档 http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return
return 409 "foobar";
应该可以。任何想法怎么了? nginx/error.log.
中没有日志
事实是,Nginx 完全按照您的要求去做。您可以通过调用 curl -v http://localhost
(或您使用的任何主机名)来验证这一点。结果看起来像这样:
* Rebuilt URL to: http://localhost/
* Hostname was NOT found in DNS cache
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost
> Accept: */*
>
< HTTP/1.1 409 Conflict
* Server nginx/1.4.6 (Ubuntu) is not blacklisted
< Server: nginx/1.4.6 (Ubuntu)
< Date: Fri, 08 May 2015 19:43:12 GMT
< Content-Type: application/octet-stream
< Content-Length: 6
< Connection: keep-alive
<
* Connection #0 to host localhost left intact
foobar
如您所见,Nginx return 是 409 和 foobar
,正如您所订购的。
所以这里真正的问题是,为什么您的浏览器在 return 代码后没有自定义文本时显示格式漂亮的错误页面,而在存在此类文本时显示灰色 "unreachable" .
答案是:因为 Content-Type
header 值。
HTTP 标准声明某些响应代码应该或必须随响应一起提供 body。为了符合标准,Nginx 这样做:每当你 return 一个没有要求的 body 的特殊响应代码时,Web 服务器发送它自己的 hardcoded HTML 响应给客户端.此响应的一部分是 header Content-Type: text/html
。这就是为什么当您在没有文本部分的情况下执行 return 409
时会看到漂亮的白色错误页面的原因 — 因此 header 您的浏览器知道 returned 数据是 HTML并将其呈现为 HTML.
另一方面,当您指定 text
部分时,Nginx 不需要发送它自己的 body 版本。所以它只是将您的文本、响应代码和与请求的文件匹配的 Content-Type
的值发送回客户端(参见 /etc/nginx/mime.types)。
当没有文件时,例如当您请求文件夹或站点根目录时,将使用默认的 MIME 类型。而这个MIME类型是application/octet-stream
,它定义了一些二进制数据。由于大多数浏览器不知道如何呈现随机二进制数据,因此它们会尽力而为,也就是说,它们会显示自己的硬编码错误页面。
这就是为什么你会得到你所得到的。
现在如果你想让你的浏览器显示你的foobar
,你需要发送一个合适的Content-Type
。类似于 text/plain
或 text/html
。通常,这可以用 add_header 完成,但在您的情况下不行,因为该指令仅适用于有限的响应代码列表(200、201、204、206、301、302、303、304 或 307 ).
我看到的唯一其他选择是将您的原始请求重写为 Nginx 熟悉的内容,以便它可以将 /etc/nginx/mime.types
中的值用于 Content-Type
:
server {
listen 80;
root /app/web;
index index.json;
location / {
rewrite ^.*$ /index.html;
return 409 "foobar";
}
}
这似乎有点 counter-intuitive 但这会起作用。
编辑:
看来 Content-Type 可以用 default_type 指令设置。所以你可以(并且应该)使用 default_type text/plain;
而不是 rewrite
行。
正在更新@ivan-tsirulev 的回答:
现在 you can set headers 甚至对于使用 always
.
错误状态代码的页面
location @custom_error_page {
return 409 "foobar";
add_header Content-Type text/plain always;
}
但是如果你设置default_type
,响应headers会有两个Content-Type headers:默认,然后添加。尽管如此,它工作正常。
以下配置对我有用:
server {
listen 80;
root /app/web;
index index.json;
location / {
return 409;
}
}
如果我点击该网站,将显示 409 页面。但是以下不起作用:
server {
listen 80;
root /app/web;
index index.json;
location / {
return 409 "foobar";
}
}
无法访问该页面。但是根据文档 http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return
return 409 "foobar";
应该可以。任何想法怎么了? nginx/error.log.
中没有日志事实是,Nginx 完全按照您的要求去做。您可以通过调用 curl -v http://localhost
(或您使用的任何主机名)来验证这一点。结果看起来像这样:
* Rebuilt URL to: http://localhost/
* Hostname was NOT found in DNS cache
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost
> Accept: */*
>
< HTTP/1.1 409 Conflict
* Server nginx/1.4.6 (Ubuntu) is not blacklisted
< Server: nginx/1.4.6 (Ubuntu)
< Date: Fri, 08 May 2015 19:43:12 GMT
< Content-Type: application/octet-stream
< Content-Length: 6
< Connection: keep-alive
<
* Connection #0 to host localhost left intact
foobar
如您所见,Nginx return 是 409 和 foobar
,正如您所订购的。
所以这里真正的问题是,为什么您的浏览器在 return 代码后没有自定义文本时显示格式漂亮的错误页面,而在存在此类文本时显示灰色 "unreachable" .
答案是:因为 Content-Type
header 值。
HTTP 标准声明某些响应代码应该或必须随响应一起提供 body。为了符合标准,Nginx 这样做:每当你 return 一个没有要求的 body 的特殊响应代码时,Web 服务器发送它自己的 hardcoded HTML 响应给客户端.此响应的一部分是 header Content-Type: text/html
。这就是为什么当您在没有文本部分的情况下执行 return 409
时会看到漂亮的白色错误页面的原因 — 因此 header 您的浏览器知道 returned 数据是 HTML并将其呈现为 HTML.
另一方面,当您指定 text
部分时,Nginx 不需要发送它自己的 body 版本。所以它只是将您的文本、响应代码和与请求的文件匹配的 Content-Type
的值发送回客户端(参见 /etc/nginx/mime.types)。
当没有文件时,例如当您请求文件夹或站点根目录时,将使用默认的 MIME 类型。而这个MIME类型是application/octet-stream
,它定义了一些二进制数据。由于大多数浏览器不知道如何呈现随机二进制数据,因此它们会尽力而为,也就是说,它们会显示自己的硬编码错误页面。
这就是为什么你会得到你所得到的。
现在如果你想让你的浏览器显示你的foobar
,你需要发送一个合适的Content-Type
。类似于 text/plain
或 text/html
。通常,这可以用 add_header 完成,但在您的情况下不行,因为该指令仅适用于有限的响应代码列表(200、201、204、206、301、302、303、304 或 307 ).
我看到的唯一其他选择是将您的原始请求重写为 Nginx 熟悉的内容,以便它可以将 /etc/nginx/mime.types
中的值用于 Content-Type
:
server {
listen 80;
root /app/web;
index index.json;
location / {
rewrite ^.*$ /index.html;
return 409 "foobar";
}
}
这似乎有点 counter-intuitive 但这会起作用。
编辑:
看来 Content-Type 可以用 default_type 指令设置。所以你可以(并且应该)使用 default_type text/plain;
而不是 rewrite
行。
正在更新@ivan-tsirulev 的回答:
现在 you can set headers 甚至对于使用 always
.
location @custom_error_page {
return 409 "foobar";
add_header Content-Type text/plain always;
}
但是如果你设置default_type
,响应headers会有两个Content-Type headers:默认,然后添加。尽管如此,它工作正常。