我有以下带重写的位置:
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;
}
}
编辑2:这里是 wellknown.conf 配置文件主体:
location ^~ /.well-known/ {
default_type "text/plain";
allow all;
}
编辑3我优化了位置,但这不会影响最终结果:
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
提前致谢
答案1
无需使用重写命令就可以做到这一点。
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
答案2
那这个呢?
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;
}
请注意,我删除了结尾的字符串字符$
,并添加了可选的尾部斜杠/?
。我还用 更改了重定向标志,last
以break
防止重定向循环。最后,目标 URL 中的尾部?
可防止 nginx 添加先前的请求参数(如果有)。该正则表达式匹配如下字符串:
/payment/gateway/v2/order/complete/123123
/payment/gateway/v2/order/complete/123123/
/payment/gateway/v2/order/complete/123123/whatever
/payment/gateway/v2/order/complete/123123/whatever?var=a
在所有这些情况下,$1
将是123123
,而重定向目的地是/payment/gateway/v2/order/complete/?order_id=123123
您可以使用 curl 测试重定向:
curl -I https://yoursite/payment/gateway/v2/order/complete/123123/whatever/you/want/?var1=1&var2=b
你应该得到以下回复Location: https://yoursite/payment/gateway/v2/order/complete/?order_id=123123
文档:http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite