Nginx返回语句不接受“文本”

时间:2015-05-08 18:29:46

标签: nginx

以下配置对我有用:

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中没有日志。

2 个答案:

答案 0 :(得分:7)

问题是,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会在您订购时返回409和foobar

因此,真正的问题是,当返回代码后没有自定义文本时,您的浏览器会显示相当格式化的错误页面,以及灰色&#34;无法访问&#34;一,当存在这样的文本时。

答案是:因为Content-Type标题值。

HTTP标准规定响应正文应该或必须附带一些响应代码。为了符合标准,Nginx执行此操作:无论何时返回没有所需主体的特殊响应代码,Web服务器都会向客户端发送自己的hardcoded HTML响应。此响应的一部分是标题Content-Type: text/html。这就是为什么你看到漂亮的白色错误页面,当你return 409没有文本部分时 - 因为这个标题你的浏览器知道返回的数据是HTML并且它将它呈现为HTML。

另一方面,当您指定text部分时,Nginx无需发送自己的正文版本。因此,它只是向客户端发回您的文本,响应代码以及与所请求文件匹配的Content-Type的值(请参阅/etc/nginx/mime.types)。

如果没有文件,例如请求文件夹或站点根目录时,则使用默认的MIME类型。此MIME类型为application/octet-stream,它定义了一些二进制数据。由于大多数浏览器不知道如何呈现随机二进制数据,因此他们尽其所能,即显示自己的硬编码错误页面。

这就是为什么你能得到你得到的东西。

现在,如果您想让浏览器显示foobar,则需要发送合适的Content-Type。类似于plain/textplain/html的内容。通常,这可以使用add_header完成,但不是在您的情况下,因为此指令仅适用于有限的响应代码列表(200,201,204,206,301,302,303,304或307) )。

我看到的唯一其他选项是将原始请求重写为Nginx熟悉的内容,以便它可以使用/etc/nginx/mime.typesContent-Type的值:

server {
    listen 80;

    root /app/web;
    index index.json;

    location / {
        rewrite ^.*$ /index.html;
        return 409 "foobar";
    }
}

这可能看起来有些违反直觉,但这样可行。

修改

似乎可以使用default_type指令设置Content-Type。因此,您可以(并且应该)使用default_type text/plain;代替rewrite行。

答案 1 :(得分:0)

更新@ ivan-tsirulev的答案:

现在,you can set标头,甚至是使用always的带有错误状态代码的页面。

location @custom_error_page {
    return 409 "foobar";
    add_header Content-Type text/plain always;
}

但是,如果您设置default_type,则响应头将具有两个Content-Type头:默认,然后添加。不过,它工作正常。