NGINX 1.13.8 重写 URL 不起作用

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

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

在这个例子中,我们使用不区分大小写的正则表达式(~*)来捕获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

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

请注意,我删除了结尾的字符串字符$,并添加了可选的尾部斜杠/?。我还用 更改了重定向标志,lastbreak防止重定向循环。最后,目标 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

相关内容