nginx rewrite 踩坑


nginx rewrite 500的故障

今天遇到的一個問題 當訪問 www.biglittleant.cn/mall 返回500,當訪問 www.biglittleant.cn/mall/返回正常的頁面。

我們來還原一下當時的情況

nginx配置文件如下:

# cat的多行內容有$等特殊字符時,須利用轉義字符\
cat >www.biglittleant.cn.conf<<EOF
server {
    listen       80;
    server_name  www.biglittleant.cn;

    location / {
        root   html;
        index  index.html index.htm;
        rewrite ^/mall(.*)\$ \$1 last;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
    error_log logs/www.biglittleant.cn.error.log debug;
}
EOF

重啟一下nginx

/data/app/nginx/sbin/nginx -t
/data/app/nginx/sbin/nginx -s reload

發起測試看看結果

[root@linux-node1 conf.d11:08:25]#curl -I http://www.biglittleant.cn/mall -x 192.168.56.11:80
HTTP/1.1 500 Internal Server Error
Server: nginx/1.12.1
Date: Thu, 30 Apr 2020 03:08:35 GMT
Content-Type: text/html
Content-Length: 537
Connection: close
ETag: "5d5e5679-219"

[root@linux-node1 conf.d11:08:35]#curl -I http://www.biglittleant.cn/mall/ -x 192.168.56.11:80
HTTP/1.1 200 OK
Server: nginx/1.12.1
Date: Thu, 30 Apr 2020 03:09:34 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Thu, 22 Aug 2019 08:46:49 GMT
Connection: keep-alive
ETag: "5d5e5679-264"
Accept-Ranges: bytes

http://www.biglittleant.cn/mall 返回500,同時error日志中增加了一行記錄

the rewritten URI has a zero length, client: 192.168.56.11, server: www.biglittleant.cn, request: "HEAD http://www.biglittleant.cn/mall HTTP/1.1", host: "www.biglittleant.cn"

通過日志分析可以發現是因為(.*) 沒有匹配到任何內容導致的報錯。

2020/04/30 11:08:35 [debug] 103857#0: *51 http script regex: "^/mall(.*)$"
2020/04/30 11:08:35 [notice] 103857#0: *51 "^/mall(.*)$" matches "/mall", client: 192.168.56.11, server: www.biglittleant.cn, request: "HEAD http://www.biglittleant.cn/mall HTTP/1.1", host: "www.biglittleant.cn"
2020/04/30 11:08:35 [debug] 103857#0: *51 http script capture: ""
2020/04/30 11:08:35 [debug] 103857#0: *51 http script regex end
2020/04/30 11:08:35 [notice] 103857#0: *51 rewritten data: "", args: "", client: 192.168.56.11, server: www.biglittleant.cn, request: "HEAD http://www.biglittleant.cn/mall HTTP/1.1", host: "www.biglittleant.cn"
2020/04/30 11:08:35 [error] 103857#0: *51 the rewritten URI has a zero length, client: 192.168.56.11, server: www.biglittleant.cn, request: "HEAD http://www.biglittleant.cn/mall HTTP/1.1", host: "www.biglittleant.cn"


2020/04/30 11:09:34 [debug] 103857#0: *52 http script regex: "^/mall(.*)$"
2020/04/30 11:09:34 [notice] 103857#0: *52 "^/mall(.*)$" matches "/mall/", client: 192.168.56.11, server: www.biglittleant.cn, request: "HEAD http://www.biglittleant.cn/mall/ HTTP/1.1", host: "www.biglittleant.cn"
2020/04/30 11:09:34 [debug] 103857#0: *52 http script capture: "/"
2020/04/30 11:09:34 [debug] 103857#0: *52 http script regex end
2020/04/30 11:09:34 [notice] 103857#0: *52 rewritten data: "/", args: "", client: 192.168.56.11, server: www.biglittleant.cn, request: "HEAD http://www.biglittleant.cn/mall/ HTTP/1.1", host: "www.biglittleant.cn"

解決辦法1

將location給規范起來,讓只有/mall/的訪問才能去rewrite。

# cat的多行內容有$等特殊字符時,須利用轉義字符\
cat >www.biglittleant.cn.conf<<EOF
server {
    listen       80;
    server_name  www.biglittleant.cn;
    location /mall/ {
        rewrite ^/mall(.*)\$  \$1  last;
    }
    location / {
        root   html;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
    error_log logs/www.biglittleant.cn.error.log debug;
}
EOF
[root@linux-node1 conf.d11:25:23]#curl -I http://www.biglittleant.cn/mall -x 192.168.56.11:80
HTTP/1.1 404 Not Found
Server: nginx/1.12.1
Date: Thu, 30 Apr 2020 03:25:27 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive

[root@linux-node1 conf.d11:25:27]#curl -I http://www.biglittleant.cn/mall/ -x 192.168.56.11:80
HTTP/1.1 200 OK
Server: nginx/1.12.1
Date: Thu, 30 Apr 2020 03:25:35 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Thu, 22 Aug 2019 08:46:49 GMT
Connection: keep-alive
ETag: "5d5e5679-264"
Accept-Ranges: bytes

通過日志可以看到,由於沒有命中 /mall/ 所以走了默認的 / 協議,自然就不會在報500的錯誤了。

2020/04/30 11:25:27 [debug] 104724#0: *57 test location: "/"
2020/04/30 11:25:27 [debug] 104724#0: *57 test location: "mall/"
2020/04/30 11:25:27 [debug] 104724#0: *57 test location: "50x.html"
2020/04/30 11:25:27 [debug] 104724#0: *57 using configuration "/"
2020/04/30 11:25:27 [error] 104724#0: *57 open() "/data/app/nginx-1.12.1/html/mall" failed (2: No such file or directory), client: 192.168.56.11, server: www.biglittleant.cn, request: "HEAD http://www.biglittleant.cn/mall HTTP/1.1", host: "www.biglittleant.cn"

解決辦法二

找到真實的需求,然后重新規划。

其實開發的需求是希望 訪問 /mall 很訪問 /mall/ 都能訪問的目錄中的index, 那這種情況,我們可以使用 try_files 來優化,配置如下:

# cat的多行內容有$等特殊字符時,須利用轉義字符\
cat >www.biglittleant.cn.conf<<EOF
server {
    listen       80;
    server_name  www.biglittleant.cn;

    location /mall {
        root   html;
        index  index.html index.htm;
        try_files \$uri \$uri/ /index.html;

    }
    location / {
        root   html;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
    error_log logs/www.biglittleant.cn.error.log debug;
}
EOF
[root@linux-node1 conf.d11:29:51]#curl -I http://www.biglittleant.cn/mall/ -x 192.168.56.11:80
HTTP/1.1 200 OK
Server: nginx/1.12.1
Date: Thu, 30 Apr 2020 03:29:53 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Thu, 22 Aug 2019 08:46:49 GMT
Connection: keep-alive
ETag: "5d5e5679-264"
Accept-Ranges: bytes

[root@linux-node1 conf.d11:29:53]#curl -I http://www.biglittleant.cn/mall -x 192.168.56.11:80
HTTP/1.1 200 OK
Server: nginx/1.12.1
Date: Thu, 30 Apr 2020 03:29:58 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Thu, 22 Aug 2019 08:46:49 GMT
Connection: keep-alive
ETag: "5d5e5679-264"
Accept-Ranges: bytes

分析: 通過日志可以看到,當前兩個都沒有命中的時候,會就url 替換成/index.html 然后重新走location匹配,命中了/ 然后返回了200.

2020/04/30 11:29:58 [debug] 104927#0: *61 http script var: "/mall"
2020/04/30 11:29:58 [debug] 104927#0: *61 trying to use file: "/mall" "/data/app/nginx-1.12.1/html/mall"
2020/04/30 11:29:58 [debug] 104927#0: *61 http script var: "/mall"
2020/04/30 11:29:58 [debug] 104927#0: *61 trying to use dir: "/mall" "/data/app/nginx-1.12.1/html/mall"
2020/04/30 11:29:58 [debug] 104927#0: *61 trying to use file: "/index.html" "/data/app/nginx-1.12.1/html/index.html"
2020/04/30 11:29:58 [debug] 104927#0: *61 internal redirect: "/index.html?"

2020/04/30 11:29:58 [debug] 104927#0: *61 rewrite phase: 1
2020/04/30 11:29:58 [debug] 104927#0: *61 test location: "/"
2020/04/30 11:29:58 [debug] 104927#0: *61 test location: "mall"
2020/04/30 11:29:58 [debug] 104927#0: *61 test location: "50x.html"
2020/04/30 11:29:58 [debug] 104927#0: *61 using configuration "/"

2020/04/30 11:29:58 [debug] 104927#0: *61 http filename: "/data/app/nginx-1.12.1/html/index.html"

遇到的問題

剛開始測試的時候 使用的是cat 重定向寫入文件,cat 會將$1 給轉義掉。導致測試結果不准確。

cat >www.biglittleant.cn.conf<<EOF
server {
    listen       80;
    server_name  www.biglittleant.cn;

    location / {
        root   html;
        index  index.html index.htm;
        rewrite ^/mall(.*)$ $1 last;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
    error_log logs/www.biglittleant.cn.error.log debug;
}
EOF
diff www.biglittleant.cn.conf www.biglittleant.cn.conf.bak
5c5
<         rewrite ^/mall(.*)$    last;
---
>         rewrite ^/mall(.*)$  $1  last;

解決辦法:

cat的多行內容有$等特殊字符時,須利用轉義字符\。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM