nginx proxy_pass url with GET params conditionally - nginx

I have a url http://foo.com/banana and I have another url http://foo.com/banana?a=1&b=2
I like that all /banana routes are handled by my local nginx, but I'd like any banana routes with GET params to be proxied to http://bar.com
so:
http://foo.com/banana -> http://foo.com/banana
http://foo.com/banana?a=1 -> (proxy) -> http://bar.com/banana?a=1
I should note this is not for production. I'm trying to redirect api calls to redirect to another server during development.
I've tried to do an 'if args' block but I can't do a proxy_pass in an if block.
I thought about doing a rewrite of:
http://foo.com/banana?a=1 -> http://foo.com/proxy?a=1
location /proxy {
proxy_pass http://bar.com;
}
But I don't have the right logic for above because bar.com is expecting the /banana route.
Any ideas?

Since this is not for production, you could stick with your original "if" solution. You only need to escape from the "if" block to be able to proxy_pass, which can be easily done with the traditional trick:
location /banana {
error_page 418 = #good_old_fallback;
if ($args) {
return 418;
}
}
location #good_old_fallback {
proxy_pass http://bar.com;
}
Your idea of using another location will also work, so if you prefer it better, you can go with something like this:
location /banana {
if ($args) {
rewrite ^/banana(.*)$ /proxy$1 last;
}
}
location /proxy {
internal;
rewrite ^/proxy(.*)$ /banana$1 break;
proxy_pass http://bar.com;
}

Related

NGINX rewrite args without an IF?

I would like to rewrite legacy links using a query parameter type of URL to a new style of URL.
Ex.
example.com/page?id=1 -> example.com/page/1
example.com/otherpage?id=1 -> example.com/otherpage/1
Currently I have the following configuration using the evil if.
if ($args ~* "id=(.*)") {
set $w1 $1;
rewrite .* $scheme://$host/page/$w1? permanent;
}
Note: I am using CloudFront, and relying on the host header above.
If the above is in a server block, with no other location block - would this qualify as a non-evil use of if in NGINX config? Also, the above only supported /page/. Any better ideas for making that portion work for otherpage and other pages?
I have seen a few other ideas discussing using a map, but I'm not quite sure how to bring it all together? I was thinking something along the lines of:
map $args_id ?? {
default ?
??
}
...
server {
...
???
}
UPDATE:
Based on the Answer from #Ivan, this was my final solution:
server {
listen 80;
root /usr/share/nginx/html;
index index.html index.htm;
# Handle legacy requests
if ($args ~* "id=(.*)") {
set $w1 $1;
rewrite ^ $scheme://$host$uri/$w1? permanent;
}
}
Your if construction isn't evil. You can use something like
rewrite ^ $scheme://$host$uri/$w1? permanent;
for any page. More complex example if you want to process both example.com/page?id=1 and example.com/page/?id=1:
map $uri $maybe_slash {
~/$ "";
default "/";
}
...
server {
...
rewrite ^ $scheme://$host$uri$maybe_slash$w1? permanent;
...
}

Is possible redirect by microservice?

Can I set a variable with an URL returned by a proxy? ... I want to avoid to run Java, PHP, Python etc. Need somethong simple and faster.
Note, to answer comments: "... an URL returned by a proxy" = a microservice that is a black-box returning the URL. Any URL, can be aleatory or function of inputs (passed to the proxy).
If it is possible, how to?
This is fine on my NGINX server, it is returning a string with the necessary URL.
location /_test {
rewrite ^/_test/(.*) /$1 break;
proxy_pass http://127.0.0.1:3000;
}
(here $1 is the input and 127.0.0.1:3000 the black-box microservice)
... How to redirect as return 301 $theNewUrl? Imagining something (illustrative and wrong of course) as
location /_test {
rewrite ^/_test/(.*) /$1 break;
set theNewUrl = proxy_pass(http://127.0.0.1:3000/$1);
return 301 $theNewUrl;
}
To redirect base on path on Ningx, try this:
example.com is your base domain.
server {
server_name myDomain;
location /_test/hello/ {
proxy_pass http://google.com/;
}
location /_test/bye/ {
proxy_pass http://stackoverflow.com/;
}
}
Example:
HTTP request to http://myDomain/_test/hello/$1 will be translated to: http://google.com/$1 you can use it with ports or whatever you want.

how to get url parameter and pass to proxy_pass using nginx

I need to get the parameter from an URL, for example, abc=MY_STRING:
https://my-address/test?abc=MY_STRING
And at the reverse proxy (my-address), is configured like this:
location /test?(.*) {
proxy_pass http://local-server:1234/test?$args
}
but it is not working.
I tried another configuration:
location /test?(.*) {
proxy_pass http://local-server:1234/test?$1
}
but not worked too.
You cannot match the query string part of the URI with a location or rewrite statement, as it is not part of the normalized URI.
But you don't need to. The URI (complete with query string) will be passed upstream
unless you redirect it using a rewrite or try_files statement.
For example:
location /test {
proxy_pass http://localhost:1234;
}
The URI /test?abc=MY_STRING will match the location and be passed to localhost:1234 exactly the same. See this document for more.

How to redirect invalid url to a valid url in nginx?

I have a valid url of the type http://example.com/valid/. Using nginx how do i redirect a url of type http://example.com/valid/dsdhshd to my valid url?
I tried:
location /valid/ {
resolver 8.8.8.8;
proxy_pass http://example.com/valid/;
proxy_redirect off;
}
But it gives a 500 internal server error.
I also tried location return 301 $scheme://example.com/valid/; but this just put me in an infinite redirection loop.
If you want to send the redirect to the client, don't proxy the request and simply send it.
server {
# Your server configuration ...
# Enclose regular expressions in default location.
location / {
location /valid {
location ~ /valid/.+ {
try_files $uri #invalid;
}
# Handle the request to the valid URL ...
}
}
location #invalid {
return 301 $scheme://$server_name/valid;
}
}
That should do the trick. You did get a redirect loop because your location block also matched the /valid/ URL itself, something you don't wanted to match. You only want to match URLs which have something after that string, e.g. /valid/foo. That is exactly what the regular expression in the location block above is ensuring.
here's a sample i could think about
server {
location /valid {
try_files $uri $uri/ #redirect_invalid;
}
location #redirect_invalid {
return 301 $scheme://$server_name/valid;
}
}
But this will be very specific and if there's many folders you'll need to add each separately, I can't think of a method to make this generic for all folders, maybe someone else could help me with this.

nginx url rewrite rule

I have URL like this
http://domain/PROD_SHEP_PDF_Downloader/DownloadPdf?favorId=10100018565295&lang=ru
I want to rewrite this part PROD_SHEP_PDF_Downloader to this SHEP_PDF_Downloader so the result will be
http://domain/SHEP_PDF_Downloader/DownloadPdf?favorId=10100018565295&lang=ru
This rule doesn't work
location /PROD_SHEP_PDF_Downloader/ {
rewrite ^/PROD_SHEP_PDF_Downloader/(.*) SHEP_PDF_Downloader/$1 break;
proxy_pass http://localhost:85;
}
Docs say that if you just want to change the URI prefix, you can use this:
location /name/ {
proxy_pass http://127.0.0.1/remote/;
}

Resources