NGINX Ingress Redirection Based On Domain Name - nginx

I have two domain names, each for different applications hosted in a single kubernetes cluster.
Is there a way to configure ingress to redirect to the different apps based on the hostname in the request it receives?
For example:
www.app1.com and www.app2.com point to the same IP address. However, I want www.app1.com to redirect to /appABC while www.app2.com redirect to /appXYZ.
I have attempted to capture the host name and use this to determine the redirect but it doesn't work.
Is what I'm trying to do possible with NGINX?

Yes,it is Possible. You must need to create two configuration files and point them to their respective paths. Please follow this link for more info and refer to this SO also to get further idea on how to use.

After some experimentation, using the NGINX Playground, I was able to come up with this solution.
...
nginx.ingress.kubernetes.io/server-snippet: |
set $is_app1_base 1;
set $is_app2_base 1;
if ($host !~ "^.*app1\.com$" ) {
set $is_app1_base 0;
}
if ($request_uri != "/") {
set $is_app1_base 0;
set $is_app2_base 0;
}
if ($is_app1_base = 1) {
return 301 $scheme://$host/appABC;
}
if ($host !~ "^.*app2\.com$" ) {
set $is_app2_base 0;
}
if ($is_app2_base = 1) {
return 301 $scheme://$host/appXYZ;
}
In case you're wondering why a number of if statements had to be used this way, NGINX is not that great with if statements and logical operations.
Another caveat worth stating here is that all ingresses associated with this NGINX controller will be affected by this server-snippet; Because nginx.ingress.kubernetes.io/server-snippet is a global annotation.

Related

How to block Nginx requests where http_referer matches requested URL

I am trying to block a webcrawler that uses the requested page as the http_referer, and I can't figure out what variable to compare it to.
e.g.
location / {
if ($the_variable_with_the_current_full_uri = $http_referer) {
return 403;
}
}
The variable has to match protocol, host, and URL, so that internal redirects from http to https don't get blocked.
So if someone requests "https://www.example.com/pages/1" with the $http_referer of "https://www.example.com/pages/1", it should be blocked.
As a secondary question, is it possible block requests on two conditions: where the above check matches, as well as matching a specific user agent string?
The full URL can be constructed by concatenating a number of variables together.
For example:
$scheme://$host$request_uri
The secondary condition could be handled using a map (see this document).
For example:
map $http_user_agent $my_http_referer {
default "";
blahblah $http_referer;
}
server {
...
if ($scheme://$host$request_uri = $my_http_referer) { return 403; }
...
}

Read query parameter from url to do a nginx redirect

I have two source URL format and want to redirect both url based on
color variant to the destination link with the parameter appended.
Scenario1: www.example.com/pages?abc=123&color=white which should redirect to www.example.com/variant1?abc=123&color=white
Scenario2: www.example.com/pages?abc=456&color=red which should redirect to www.example.com/variant2?abc=456&color=red
I have tried with below , it works for one but not for both as its specific. Not able find the solution for both cases, as else doesnt work
location = /pages {
if ($args ~* "&color=white”) {
rewrite ^.*$ /variant1 redirect;
} }
While it is possible to do this in Nginx, it'll defeat some of the advantages that Nginx provides. If you can, it's better to do it within your application code or Lua.
If you choose to go forward with if statements, you'll want to match against individual $arg_* variables rather than $args. In particular, you'll want to use $arg_color, which will contains the color querystring value.
location = /pages {
if ($arg_color = "white") { return 301 /variant1$is_args$args; }
if ($arg_color = "red") { return 301 /variant2$is_args$args; }
# If we get to this point, there was no match. You have to keep
# this very simple and can only use directives documented as being
# compatible with `if`, or you'll get all sorts of crazy bugs and
# crashes.
return 404.
}

Nginx rewrite: how to change URL from dynamic to static

I'm configuring nginx as reverse proxy.
I need to change (rewrite?) the URLs, example: when the request (to nginx Reverse Proxy) is "http://example.com/test/?username=test1;password=passwdtest1" it will must "modified" to the main server as "http://example.com/test/?username=production;password=passwdproduction1".
Consider that in the original request the fields "username=test1;password=passwdtest1" are not always the same (they changes), instead the "modified" to the main server are always the same.
Others example to be more clear:
"/test/?username=test1;password=passwdtest1" -> "/test/?username=production;password=passwdproduction1"
"/test/?username=test1876;password=somepasswd" -> "/test/?username=production;password=passwdproduction1"
"/test/?username=somevalues;password=somepasswdvalue" -> "/test/?username=production;password=passwdproduction1"
So, independently to what are the values of "?username=somevalues;password=somepasswdvalue" it should always become "?username=production;password=passwdproduction1".
Thanks for your help!
A little late on the answer but this should work for you:
location ~* /test/? {
if ($arg_username ~ "^$|\s+") { return 404; }
if ($arg_password ~ "^$|\s+") { return 404; }
rewrite ^ /test?username=production&password=passwdproduction1? permanent;
}
The code above checks if it is within the example.com/test path. If it is it will check if the user name or the password variable are present and not empty in the query string. In case if any isn't present or is empty it will return a 404 else it will redirect you to the preferred url.
By the way, instead of the semicolon in your example urls I would use an ampersand (&).

Custom routing in load balancer

Is it possible to define a custom routing in NGINX or other Load Balancer?
I.e. I have a cookie or a header and based on its value I decide which backend server to choose?
I need some very simple logic - values a1,a2,a3 - to server A, values b1,b2 to server B, all other to server C
In nginx you can do it simply by using if:
location / {
if ($http_cookie ~* "yourcookiename=a") {
proxy_pass http://upstream_a;
break;
}
if ($http_cookie ~* "yourcookiename=b") {
proxy_pass http://upstream_b;
break;
}
proxy_pass http://upstream_c;
}
This is simple regexp , so this way if "yourcookiename" has value a1,a2 etc. it will go to uprstream_a and so on.
Hope it helps...
If you need some sticky session, there are open source third party modules that can do that with nginx, while the native implementation is part of the commercial subscription. Also, tengine, an open source chinese fork of nginx developed by Alibaba can do that natively.
If you want to do it the custom way, use a map to avoid processing a chain of if blocks for all requests. This is also better for readability. For instance, using a cookie :
map $cookie_mycookie $node {
"~^a[1-3]$" "A";
"~^b[1-2]$" "B";
default "C";
}
server {
location / {
proxy_pass http://$node;
}
}

nginx - response based on the requested header

I have nginx 1.0.8 installed.
here is my problem:
I have 2 files : file1.js and file2.js. the requested path is something like this:
www.mysite.com/files_dir/%user%/file.js
If the requested header : "X-Header" exists and has the value "OK" then the responded content should be file1.js else file2.js.
The files are situated in "html/files_dir" and %user% is a set of directories that represents the usernames registered through my service.
How do I configure this in nginx? I'm not interested in php, asp or similar technologies only if it's possible with nginx.
Thanks
map lets you define a variable's value based on another variable. map should be declared at http level (i.e. outside of server):
map $http_x_header $file_suffix {
default "2";
OK "1";
};
Then the following location should do the trick using your new variable $file_suffix
location ~ ^(/files_dir/.+)\.js$ {
root html;
try_files $1$file_suffix.js =404;
}
You could do this with nginx very easily. This is example:
location /files_dir/ {
set $file = file2.js;
if ( $http_x_header = OK ) {
set $file = file1.js;
}
rewrite ^(/files_dir/.*)/file.js$ $1/$file last;
}
You could read about HTTP variables in NGINX here , and about nginx rewrite module here

Resources