Nginx返回语句不接受"文本"

Upv*_*ote 3 nginx

以下配置对我有用:

server {
  listen 80;

  root /app/web;
  index index.json;

  location / {
    return 409;
  }
}
Run Code Online (Sandbox Code Playgroud)

如果我点击网站,将显示409页面.但是以下不起作用:

server {
  listen 80;

  root /app/web;
  index index.json;

  location / {
    return 409 "foobar";
  }
}
Run Code Online (Sandbox Code Playgroud)

页面无法访问.但根据文档http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return

return 409 "foobar";
Run Code Online (Sandbox Code Playgroud)

应该管用.任何想法都错了吗?nginx/error.log中没有日志.

Iva*_*lev 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
Run Code Online (Sandbox Code Playgroud)

如您所见,Nginx返回409和foobar您订购的.

因此,真正的问题是,当返回代码后没有自定义文本时,您的浏览器会显示格式错误的页面,而当存在此类文本时,灰色的"无法访问"文本.

答案是:因为Content-Type标头值.

HTTP标准规定响应主体应该或必须附带一些响应代码.为了符合标准,Nginx执行此操作:无论何时返回没有所需主体的特殊响应代码,Web服务器都会将自己的硬编码 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/text或的东西plain/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";
    }
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:

看来Content-Type可以使用default_type指令设置.所以你可以(而且应该)使用default_type text/plain;而不是rewrite线.

  • 哇,谢谢您提供的这个全面的解决方案。我测试了default_type并且它有效。谢谢你! (2认同)