2015-05-08 44 views
2

以下配置爲我工作:不接受「文本」的Nginx return語句

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中沒有日誌。

回答

6

事情是,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,您訂購。

因此,這裏真正的問題是,爲什麼你的瀏覽器中顯示了相當格式化的錯誤頁面時,有返回代碼後沒有自定義文本,灰色「無法訪問」之一,當這樣的文本存在。

答案是:因爲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指令進行設置。所以你可以(也應該)使用default_type text/plain;而不是rewrite這條線。

+0

哇謝謝你這個全面的解決方案。我測試了default_type,它工作。謝謝! –