Double if breaks url - nginx

We have following config:
location / {
#This statement adding extra slash to url
if ($http_cookie !~ 'skip_geo=yes') {
set $allow_visit "${allow_visit}_at_all";
}
if ($allow_visit = no_at_all) {
rewrite ^ http://domain/block.html;
}
proxy_pass http://backend/;
}
Why extra slash is added?
Config can be fixed by removing slash from proxy_pass, but whole story looks unstable.

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

convert url get parameters to url segment in nginx

I have this URL https://example.com/user?param1=value1&param2=value2&param3=value3
and have it to go to https://example.com/user/value1/value2/value3 on the Nginx server.
Just FYI it is WordPress site and I have added the following rule in the Nginx config file.
location ~ /user/ {
if ($args ~* "^param1=(\d+)&param3=(\d+)&param3=(\d+)") {
set $param1 $1;
set $param2 $1;
set $param3 $1;
set $args '';
rewrite ^.*$ /user/$param1/$param2/$param3 permanent;
}
}
Your solution has two errors, 1) the location does not match /user, and 2) the rewrite is also appending the original arguments.
This could be fixed by using an exact match location and a trailing ? on the rewrite. For example:
location = /user {
...
rewrite ^ /user/$param1/$param2/$param3? permanent;
}
However, the map statement is a cleaner and extensible solution, for example:
map $request_uri $redirect {
default 0;
~*^/user?param1=(?<p1>\d+)&param2=(?<p2>\d+)&param3=(?<p3>\d+)$ /user/$p1/$p2/$p3;
}
server {
...
if ($redirect) { return 301 $redirect; }
...
}
See this document for details.

How to write nginx rules/regexes to match empty non empty path

I want to have an nginx rule that will proxy requests with empty path / to a back end server, and another rule that match non empty paths, ex. http://mysite/x/y/z
The following two rules do not do this, the second one is catching all:
# empty path
location ^/?$ {
proxy_pass http://127.0.0.1:8000;
}
location / {
expires -1;
alias /var/static-site/;
}
I have tried /.*/ for the second rule, without success...
Use the "=" modifier to process an exact match on "/":
location = / {
proxy_pass http://127.0.0.1:8000;
}
location / {
expires -1;
alias /var/static-site/;
}

nginx rewrite with the value of the query string only

I want to redirect from
www.setup.com/view.php?id=213
to
www.setup.com/213
this is my nginx redirect
location ^~ view.php {
if ($query_string ~ "^id=([0-9-]+)$"){
rewrite ^/view.php$ http://$server_name/%1? break;
}
}
For some reason it appends
?id= to the url
so it becomes
www.setup.com?id=213
how can I remove
?id= from the url?
Use :
location / {
rewrite ^/view.php$ /$arg_id? redirect;
}

Nginx proxy pass and url rewriting

How to trig this rule only when I have GET parameters(query string) in url,
otherwise I will match on an alias.
location ~^/static/photos/.* {
rewrite ^/static/photos/(.*)$ /DynamicPhotoQualitySwitch/photos/$1 break;
expires 7d;
proxy_pass http://foofoofoo.com;
include /etc/nginx/proxy.conf;
}
The 1st way that I know of is using a regex against the $args parameter like so:
if ($args ~ "^(\w+)=") {
Or the 2nd way is to use the convenient $is_args like so:
if ($is_args != "") {
Remember that in both styles you need to put a space between the if and the opening parenthesis; "if (" not "if(" as well as a space after the closing parenthesis and the opening brace; ") {" rather than "){".
Full example using the 1st style above, nginx.conf:
location ~^/static/photos/.* {
include /etc/nginx/proxy.conf;
if ($args ~ "^(\w+)=") {
rewrite ^/static/photos/(.*)$ /DynamicPhotoQualitySwitch/photos/$1 break;
expires 7d;
proxy_pass http://foofoofoo.com;
}
}
Full example using the 2nd style above, nginx.conf:
location ~^/static/photos/.* {
include /etc/nginx/proxy.conf;
if ($is_args != "") {
rewrite ^/static/photos/(.*)$ /DynamicPhotoQualitySwitch/photos/$1 break;
expires 7d;
proxy_pass http://foofoofoo.com;
}
}
Note that the proxy.conf include goes outside of the if statement.
Version:
[nginx#hip1 ~]$ nginx -v
nginx version: nginx/1.2.6
And some info on the $args and $is_args variables:
http://nginx.org/en/docs/http/ngx_http_core_module.html
Reading the docs is always useful, I just discovered that $query_string is the same as $args, so where I have $args above, you could also use $query_string according to the docs.
IMPORTANT
It is important to note however, that If can be Evil!
And therefore either test thoroughly or use the recommendation provided in the link above to change the URL inside location statement in a way similar to the example provided there, something like:
location ~^/static/photos/.* {
error_page 418 = #dynamicphotos;
recursive_error_pages on;
if ($is_args != "") {
return 418;
}
# Your default, if no query parameters exist:
...
}
location #dynamicphotos {
# If query parameters are present:
rewrite ^/static/photos/(.*)$ /DynamicPhotoQualitySwitch/photos/$1 break;
expires 7d;
include /etc/nginx/proxy.conf;
proxy_pass http://foofoofoo.com;
}

Resources