NGINX 1.13.8 Rewrite url not works

This should be possible to do without using the rewrite command.

location ~* /payment/gateway/v2/order/complete/(.+)$ {
    proxy_pass http://api.test.com:8085/payment/gateway/v2/order/complete?order_id=$1;
} 

In this example we use the case insensitive regex (~*) to capture everything after complete in the URL, then inside the location we rebuild the request using the $1.

To test the setup, I added a configuration to my 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;
    }
}

This is configured so that a successful hit will be proxied to the other server and return a 202, and any unsuccessful hit will result in a 40x response.

This can be tested from the 'client side' using curl, like this:

$ 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

And seeing the logs, we observe two entries:

  1. The connection from the 'client' to the 'frontend' with the original path:
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. The connection from the 'frontend' to the 'backend' which includes the modified path:
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"

This could also be cleaned up a bit to only match requests that contain a valid ID using a more complex regex. Nginx supports full PCRE for match/set expressions.

Source: https://nginx.org/en/docs/http/ngx_http_core_module.html#location


What about this?

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

Note that I have removed the end string char $ and that I have added an optional trailing slash /?. I have also changed the redirect flag last with break to prevent redirection loops. Finally, the trailing ? in the destination URL prevents nginx from adding the previous request arguments if there were any. That regular expression matchs strings like these:

/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

In all those cases, $1 would be 123123 and the redirect destination is /payment/gateway/v2/order/complete/?order_id=123123

You can test the redirection with curl:

curl -I https://yoursite/payment/gateway/v2/order/complete/123123/whatever/you/want/?var1=1&var2=b

You should get a response with Location: https://yoursite/payment/gateway/v2/order/complete/?order_id=123123

Documentation: http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite