Is possible redirect by microservice? - nginx

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.

Related

how in nginx to redirect location to any host received urls?

I need to get the host address from the request and redirect to another host with the rewritten address, but in all possible ways I failed
Here's an example (one of the attempts):
location / {
proxy_pass http://...;
...
}
location /service/(.*)$/ {
rewrite /service/$1/(.*)$ /$2 break;
proxy_pass http://$1.localhost:8080/;
...
}
Works only if hardcoded:
location /service/hostaname/ {
rewrite /service/hostaname/(.*)$ /$1 break;
proxy_pass http://hostaname.localhost:8080/;
...
}
But this is not a suitable solution for me
Help meeeeeee, thanks!
Your location syntax is invalid, as it is missing the regular expression operator. The rewrite statement contains an invalid regular expression.
You do not need the rewrite statement as you can extract the parts of the URI from the location statement.
For example:
location ~ ^/service/([^/]+)/(.*)$ {
proxy_pass http://$1.localhost:8080/$2;
}
You may need to define a resolver statement as the proxy_pass contains variables. See this document for details.

How to get nginx to do a redirect to url-encoded query parameter

I have a requirement to do a proxy call to url delivered via a query parameter as per example:
My nginx proxy is deployed at: https://myproxy.net
if the redirect parameter is not url encoded I can do the call with this block:
location /basepath {
if ( $arg_redirect = '') {
return 400 "Missing redirect directive in request";
}
proxy_pass $arg_redirect;
proxy_intercept_errors on;
error_page 301 302 307 = #handle_redirects;
}
the error intercepts and #handle_redirects then take care of othe 30X codes that might pop up at new destination.
This works for a request:
GET: https://myproxy.net/basepath?redirect=https://destination.com/somepath/uuid
What do I need to do to make it work for:
GET: https://myproxy.net/basepath?redirect=https%3A%2F%2Fdestination.com%2Fsomepath%2Fuuid
Additionally as part of spec it has to be pure nginx, not additional modules, lua etc.
Thanks!
Actually, proxy_pass does normalisation by default, but it only affects $uri part. Thus you only need to decode the beginning of the passed string to get it working:
location / {
if ( $arg_redirect = '') {
return 400 "Missing redirect directive in request";
}
if ( $arg_redirect ~ (.+)%3A%2F%2F(.+) ){ # fix :// between scheme and destination
set $arg_redirect $1://$2;
}
if ( $arg_redirect ~ (.+?)%3A(.*) ){ # fix : between destination and port
set $arg_redirect $1:$2;
}
if ( $arg_redirect ~ (.+?)%2F(.*) ){ # fix / after port, the rest will be decoded by proxy_pass
set $arg_redirect $1/$2;
}
proxy_pass $arg_redirect;
}
With the above I managed to access http://localhost/?redirect=http%3A%2F%2F127.0.0.1%3A81%2Fsfoo%20something%2Fs
The solution seems dirty and the only alternative using default modules is map (even less cleaner in my opinion). I'd rather split redirect argument into pieces: scheme (http or https), destination, port, and uri. With that you would be able to construct full address without rewriting:
proxy_pass $arg_scheme://$arg_dest:$arg_port/$arg_uri
Ok, there is very weird and curious solution
server {
listen 80;
resolver x.x.x.x;
location /basepath {
if ($arg_redirect = '') {
return 400 "Missing redirect directive in request";
}
proxy_pass http://127.0.0.1:80/basepath/$arg_redirect;
}
location ~ ^/basepath/(?<proto>\w+):/(?<redir>.+)$ {
proxy_pass $proto://$redir;
}
}
Nginx does not encode path with variables in proxy_pass and send it as is. So, I make $arg_* part of proxy_pass uri, send request to self and nginx will receive new request which will be decoded.
But because Nginx will clean path and replace // to / I split protocol part in regexp.
And ... I would never recommend using this solution, but it works :)
try like this and let me know if it works
location /basepath {
if ( $arg_redirect = '') {
return 400 "Missing redirect directive in request";
}
set_unescape_uri $decodedredirect $arg_redirect;
proxy_pass $decodedredirect;
proxy_intercept_errors on;
error_page 301 302 307 = #handle_redirects;
}

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.

nginx proxy_pass url with GET params conditionally

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

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.

Resources