Nginx
NGINX 1.13.8 重寫 url 不起作用
我有以下重寫位置:
location ~ ^/payment/gateway/v2/order/complete/(.*)$ { proxy_pass http://api.test.com:8080/payment/gateway/v2/order/complete?order_id=$1; }
然後我嘗試了這個:
location /payment/gateway/v2/order/complete { rewrite ^/payment/gateway/v2/order/complete/(.+) /payment/gateway/v2/order/complete?order_id=$1 break; proxy_pass http://api.test.com:8080 }
那麼這個:
location /payment/gateway/v2/order/complete/ { rewrite ^/payment/gateway/v2/order/complete/$ /payment/gateway/v2/order/complete?order_id=$1 last; proxy_pass http://api.test.com:8080 }
那麼這個:
location /payment/gateway/v2/order/complete { rewrite ^/payment/gateway/v2/order/complete/([^/]+)$ /payment/gateway/v2/order/complete?order_id=$1 last; proxy_pass http://api.test.com:8080; }
所有這些都不起作用。
**編輯:**這是完整的 nginx 配置:
server { listen 443 ssl; server_name api.test.com www.api.test.com; ssl_certificate /home/ssl/api.test.com/cert.pem; ssl_certificate_key /home/ssl/api.test.com/key.pem; ssl_protocols SSLv3 TLSv1.2; ssl_ciphers "RC4:HIGH:!aNULL:!MD5:!kEDH"; add_header Strict-Transport-Security 'max-age=604800'; access_log /var/log/nginx/api.test.access.log; error_log /var/log/nginx/api.test.error.log; root /home/test; include /etc/nginx/conf/wellknown.conf; location /payment/paypal { proxy_pass http://api.test.com:8080; } location /payment/visa { proxy_pass http://api.test.com:8080; } location /payment/gateway { proxy_pass http://api.test.com:8080; } location /payment/gateway/order/complete { proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; proxy_set_header SERVER_PORT $server_port; proxy_set_header REMOTE_ADDR $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://api.test.com:8080; } location /payment/gateway/v2/order/complete { rewrite ^/payment/gateway/v2/order/complete/(.+) /payment/gateway/v2/order/complete?order_id=$1 break; proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; proxy_set_header SERVER_PORT $server_port; proxy_set_header REMOTE_ADDR $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://api.test.com:8080; } location /payment/mastercard/order { proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; proxy_set_header SERVER_PORT $server_port; proxy_set_header REMOTE_ADDR $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://api.test.com:8080; } location /payment/mir/order { proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; proxy_set_header SERVER_PORT $server_port; proxy_set_header REMOTE_ADDR $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://api.test.com:8080; } location /payment/v1 { proxy_pass http://api.test.com:8080; } location /catalog { proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; proxy_set_header SERVER_PORT $server_port; proxy_set_header REMOTE_ADDR $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://localhost:9202; } location / { if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Locale'; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain charset=UTF-8'; add_header 'Content-Length' 0; return 204; } if ($request_method = 'POST') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'; add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'; } if ($request_method = 'GET') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'; add_header 'Access-Control-Expose-Headers' 'Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'; } } location /test-rpc { proxy_pass http://api.test.com:8080; } }
EDIT2:這裡 wellknown.conf 配置文件正文:
location ^~ /.well-known/ { default_type "text/plain"; allow all; }
EDIT3我優化了位置,但不影響最終結果:
server { listen 443 ssl; server_name api.test.com www.api.test.com; ssl_certificate /home/ssl/api.test.com/cert.pem; ssl_certificate_key /home/ssl/api.test.com/key.pem; ssl_protocols SSLv3 TLSv1.2; ssl_ciphers "RC4:HIGH:!aNULL:!MD5:!kEDH"; add_header Strict-Transport-Security 'max-age=604800'; access_log /var/log/nginx/api.test.access.log; error_log /var/log/nginx/api.test.error.log; root /home/test; include /etc/nginx/conf/wellknown.conf; location /payment/gateway/v2/order/complete { rewrite ^/payment/gateway/v2/order/complete/(.+) /payment/gateway/v2/order/complete?order_id=$1 break; proxy_pass http://api.test.com:8085; } location /payment { proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; proxy_set_header SERVER_PORT $server_port; proxy_set_header REMOTE_ADDR $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://api.test.com:8085; } location /catalog { proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; proxy_set_header SERVER_PORT $server_port; proxy_set_header REMOTE_ADDR $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://localhost:9202; } location / { if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Locale'; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain charset=UTF-8'; add_header 'Content-Length' 0; return 204; } if ($request_method = 'POST') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'; add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'; } if ($request_method = 'GET') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'; add_header 'Access-Control-Expose-Headers' 'Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'; } } location /test-rpc { proxy_pass http://api.test.com:8080; } }
Nginx 版本 1.13.8
提前致謝
這應該可以在不使用 rewrite 命令的情況下完成。
location ~* /payment/gateway/v2/order/complete/(.+)$ { proxy_pass http://api.test.com:8085/payment/gateway/v2/order/complete?order_id=$1; }
在此範例中,我們使用不區分大小寫的正則表達式 (
~*
) 來擷取complete
URL 中的所有內容,然後在該位置內使用 $1 重建請求。為了測試設置,我在我的 nginx 中添加了一個配置:
server { listen 80; server_name localhost; location ~* /payment/gateway/v2/order/complete/(.+)$ { proxy_pass http://localhost:8085/payment/gateway/v2/order/complete?order_id=$1; } location / { return 404; } } server { listen 8085; server_name localhost; location ~ /payment/gateway/v2/order/complete(.*) { return 202; } }
這被配置為成功命中將被代理到其他伺服器並返回 202,任何不成功的命中將導致 40x 響應。
這可以使用 curl 從“客戶端”進行測試,如下所示:
$ curl -v http://localhost:80/payment/gateway/v2/order/complete/1234 -L * Trying 127.0.0.1:80... * TCP_NODELAY set * Connected to localhost (127.0.0.1) port 80 (#0) > GET /payment/gateway/v2/order/complete/1234 HTTP/1.1 > Host: localhost > User-Agent: curl/7.68.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 202 Accepted < Server: nginx/1.18.0 (Ubuntu) < Date: Thu, 12 Nov 2020 02:02:12 GMT < Content-Type: application/octet-stream < Content-Length: 0 < Connection: keep-alive < * Connection #0 to host localhost left intact
查看日誌,我們觀察到兩個條目:
- 使用原始路徑從“客戶端”連接到“前端”:
127.0.0.1 - - [12/Nov/2020:02:02:12 +0000] "GET /payment/gateway/v2/order/complete/1234 HTTP/1.1" 202 0 "-" "curl/7.68.0"
- 從“前端”到“後端”的連接,包括修改後的路徑:
127.0.0.1 - - [12/Nov/2020:02:02:12 +0000] "GET /payment/gateway/v2/order/complete?order_id=1234 HTTP/1.0" 202 0 "-" "curl/7.68.0"
這也可以稍微清理一下,以僅使用更複雜的正則表達式匹配包含有效 ID 的請求。Nginx 支持完整的 PCRE 匹配/設置表達式。
來源:https ://nginx.org/en/docs/http/ngx_http_core_module.html#location