Nginx 405 以及301 解決報錯記錄

weiweiyi發表於2023-03-04

背景

前端時間上線專案的時候,由於第一次上線沒有經驗。報了幾個錯誤。

405 Not allowed

當時的nginx.conf配置


server {
    listen       80 default_server;
    listen  [::]:80 default_server;

    access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://gitlabwebhooktogithub-api:8088/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
405 報錯

伺服器上使用 nginx 啟動的時候 並訪問如下時,報了 405 Not allowed 異常

http://gitlab-webhook-to-github.xxxxxx:17081

去谷歌了一下,說是這個問題出現的原因是因為使用了 post 請求去獲取靜態資源,

我覺得很奇怪,明明是用post請求後臺介面,為什麼變成請求靜態資源,是因為專案打包後變成靜態了嗎?

感覺可能對靜態資源理解不對,抱著這個想法,我把靜態資源的概念又梳理了一遍:

靜態資源:指的就是在 js/css/jpg/png/xxx.json... 等等這些在前端工程中需要提前配置或者編譯之後的檔案,而且這些檔案並不會時刻變化或者說變化週期比較長。
同時 Apache、IIS、Nginx等絕大多數web伺服器,都不允許靜態檔案響應POST請求。
嘗試解決

同時,那篇文章下面還給瞭解決方式:

在 location 中配置 error_page,這個解決問題的思路是將 post 請求轉換成 get 請求,配置資訊如下:

server {
    listen       80;
    server_name  域名;
   location /{
       root /www/檔案目錄;
       index index.html index.htm index.php;
       error_page 405 =200 http://$host$request_uri;
    }
 }

但是沒有效果,報錯依舊。

檢視後臺是否收到請求

既然方法沒有效果,那就看看後臺服務的日誌有沒有收到請求。

於是在application.yml 新增了 日誌功能,將日誌列印到本目錄到 my.log 檔案中

server:
  port: 8088

logging:
  file: my.log

在後臺的介面上列印資訊,若收到請求,則列印。
logger.info("接收到請求");

檢視日誌: 後臺沒有收到請求
image.png

也就是說所有的請求(包括 get)都沒有到達後臺

於是我又去檢視了 url 以及 nginx配置

location /api/ {
    proxy_pass http://gitlabwebhooktogithub-api:8088/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}


需要加上 api 字尾,才能轉發給後臺。真是粗心大意

301 Moved Permanently

加上 api 字尾後, url為

http://gitlab-webhook-to-github.xxxxxx:17081/api 

之後又發生了新的報錯: 301 Moved Permanently

<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr>
<center>nginx/1.23.1</center>
</body>
</html>

為啥服務端會返回301呢?

首先需要弄清楚狀態碼的含義, HTTP協議中3xx開頭的狀態響應碼都是表示重定向的響應。根據RFC的定義:

  • 301 Moved Permanently
  • 302 Found
  • 303 See Other
  • 307 Temporary Redirect

301是永久重定向。如果使用Nginx作為HTTP伺服器,那麼當使用者輸入一個不存在的地址之後,基本上會有兩種情況:

  1. 返回404狀態碼,
  2. 返回301狀態碼和重定向地址。只說下301 Moved Permanently的處理過程。

下面這種情況 Nginx 會主動設定3 01 Moved Permanently 狀態碼:

當使用者在瀏覽器輸入了一個url地址,末尾部分是一個檔案目錄且不以斜槓”/“結尾,比如 “www.baidu.com/index” 。
Nginx沒有找到index這個檔案,但發現了index是個目錄。於是本次訪問的返回狀態碼就會被設定成301 Moved Permanently。

流程圖:
image.png

原因就是: url對應的位置為目錄

再去後臺找發現: @RequestMapping("")

猜想是不是需要加 / 才能正常訪問此controller

@RestController
@RequestMapping("")
@Slf4j
public class GitLabController {

    @Autowired
    private NotifySchedule notifySchedule;

    @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity pushHook(@RequestBody String json,
                               @RequestHeader(name = "X-Gitlab-Event") String event,
                               @RequestHeader(name = "X-Gitlab-Token", required = false) String secret) {
        if (secret == null) {
            ResponseVo body = ResponseUtil.error(HttpStatus.UNAUTHORIZED,"未在系統中新增secret, 請求失敗");
            return  new ResponseEntity<>(body, HttpStatus.UNAUTHORIZED);
        }
       return notifySchedule.putIntoMap(json, event, secret);
    }
}

之後又在 api 下 加了個斜槓 /

http://gitlab-webhook-to-github.xxxxxx:17081/api/

果然訪問成功。

image.png


為什麼重定向自動加的斜槓不生效

回過頭一想, 重定向的時候不是自動加上了 斜槓/ ,為什麼也沒有成功?

image.png

再去重定向的地址一看:沒有自動加上 埠號,導致重定向失敗

總結:

第一個錯誤,url不對導致沒有轉發給後臺
第二個錯誤,url不對導致沒有訪問到正確的controller

相關文章