Nginx

NGINX 1.13.8 重寫 url 不起作用

  • November 12, 2020

我有以下重寫位置:

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;
} 

在此範例中,我們使用不區分大小寫的正則表達式 ( ~*) 來擷取completeURL 中的所有內容,然後在該位置內使用 $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

查看日誌,我們觀察到兩個條目:

  1. 使用原始路徑從“客戶端”連接到“前端”:
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"
  1. 從“前端”到“後端”的連接,包括修改後的路徑:
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

引用自:https://serverfault.com/questions/1041221