nginx alternative for proxy_pass directive within if statement - if-statement

I've got the following NGINX configuration:
- location /concepts {
auth_basic "off";
if ($http_accept ~ 'application/json') { set $isapirequest "true"; }
if ($http_accept ~ 'application/ld\+json') { set $isapirequest "true"; }
if ($http_accept ~ 'application/hal\+json') { set $isapirequest "true"; }
if ( $isapirequest = "true" ) { proxy_pass http://127.0.0.1:5315/search/concepts/; }
if ( $isapirequest != "true" ) {
rewrite ^/concepts$ /concepts/ redirect;
rewrite ^(.*)$ /blah$1 last;
}
include add_cors_headers_OPTIONS_HEAD_GET_PUT_DELETE;
}
The error that I'm getting is:
\"proxy_pass\" cannot have URI part in location given by regular expression, or inside named location, or inside \"if\" statement, or inside \"limit_except\"
Can you guys think of any way on NGINX to achieve the above without using an "if" statement?

Your last two if statements are mutually exclusive, so one of them can be eliminated, which would remove the error you are getting.
This document indicates which statements should be used inside an if block within a location context. You might consider using a map to replace all but one of the if statements.
For example:
map $http_accept $redirect {
default 1;
~application/json 0;
~application/ld\+json 0;
~application/hal\+json 0;
}
server {
...
location /concepts {
auth_basic "off";
if ($redirect) {
rewrite ^(.*)$ /blah$1 last;
}
proxy_pass http://127.0.0.1:5315/search/concepts;
include add_cors_headers_OPTIONS_HEAD_GET_PUT_DELETE;
}
...
}
The rewrite ^/concepts$ /concepts/ redirect; statement can be moved to the location that processes the /blah/concepts URI, and rewritten as rewrite ^/blah/concepts$ /concepts/ redirect;.
See this document for more.

Related

How do I create a proxy_pass junction by header value in NGINX?

I would like to do something like this:
location / {
if($http_x_my_header == 'some-value') {
proxy_pass "https://a/";
}
# else
proxy_pass "https://b/";
}
Because I know that using "IF" in NGINX can be kind of problematic: How would I solve this following "best practices"?

Nginx match against variable

I try to check based on the request URI and OIDC roles in HTTP header if the user has access to a specific directory.
Currently I use statically defined
server {
location /tool/ {
location /tool/abc/ {
if ($http_x_auth_roles !~ '(^|,)MY_DEFINED_ROLE_FOR_abc(,|$)') {
return 403;
}
}
# and so on for every single tool
}
}
I tried to switch to a generic variant but the matching does not work:
map $request_uri $expected_role {
default 'DOES_NOT_MATCH';
'~^/tool/(.+)/' 'MY_DEFINED_ROLE_FOR_$1';
}
server {
location /tool/ {
if ($http_x_auth_roles !~ $expected_role) {
return 403;
}
}
}
I checked the content of $expected_role and it's showing exactly what I want, but it never matches. Is there some kind of work around to achieve what I want?

NGINX - rewrite rule with regular expression

I have an url ex. www.something.com/cdn/util/sacle/180/180/...... I need to rewrite it to the www.something.com/cdn/_util/scale.php/180/180.... How can I do it in nginx? My solution now:
location /cdn/ {
rewrite ^/util/scale(.*)$ /_util/scale.php/$1 break;
}
But it is not a good solution for me, because I have some other rewrite rule:
location /serve {
rewrite ^/serve(.*)$ /_util/serve.php/$1 break;
}
location /upload {
rewrite ^/upload(.*)$ /_util/upload.php/$1 break;
}
location /delete {
rewrite ^/delete(.*)$ /_util/delete.php/$1 break;
}
location /copy {
rewrite ^/copy(.*)$ /_util/copy.php/$1 break;
}
location /move {
rewrite ^/move(.*)$ /_util/move.php/$1 break;
}
location /util {
rewrite ^/util/placeholder(.*)$ /_util/placeholder.php/$1 break;
rewrite ^/util/thumb(.*)$ /_util/thumb.php/$1 break;
rewrite ^/util/scale(.*)$ /_util/scale.php/$1 break;
rewrite ^/util/marker(.*)$ /_util/marker.php/$1 break;
}
I think it is possible in one line too. And the php got the parameters from the url. Which is now working, if I write the url like this:
http://cdn-staging.something.com/util/scale/180/180/dev-employer-images/iamge.jpg
It is create this:
http://cdn-staging.something.com/_util/scale.php/180/180/dev-employer-images/iamge.jpg
But it is under Apache, and I need to make it to nginx.

NGINX rewriting subfolder when folder already rewritten?

I have
/site/clients/anything
rewriting to
/site/clients/index.php?action=$1
however i also want to rewrite
/site/clients/verify/anything
to
/site/clients/verify/index.php?VID=$1
Things i've tried
location / {
try_files $uri $uri/ #extensionless-php;
rewrite ^/site/clients/verify/(.+)$ /site/clients/verify/index.php?VID=$1;
rewrite ^/site/clients/^(?!login|sign-up|verify\/.*$).*$ /site/clients/index.php?action=$1;
index index.php index.html;
}
location ~ /site/clients/verify/(.+)$ {
rewrite ^/site/clients/verify/(.+)$ /site/clients/verify/index.php?VID=$1;
}
location ~ /site/clients/^(?!login|sign-up|verify\/.*$).*$ {
rewrite ^/site/clients/^(?!login|sign-up|verify\/.*$).*$ /site/clients/index.php?action=$
}
location ~ /site/clients/^((?!login|sign-up|verify).)*$ {
rewrite /site/clients/^((?!login|sign-up|verify).)*$ /site/clients/index.php?action=$1;
}
Is this even possible?
No progess has been made.

How do I redirect all requests that does NOT contain certain string to 400 using nginx

I am trying to block or redirect to 400 all the requests which does not contain certain strings or keyword in the uri. I am looking for a solution using nginx.
Specifically on "NOT containing strings". If it is not possible with ! (NOT) matching, is there any alternative.
I would recommend using a map:
map $uri $bad_request {
# start by assuming it's a bad request
default 1;
# if any of the following match, clear the $bad-request variable
~a-required-string 0;
~another-required-string 0;
# ...
}
location / {
if ($bad_request) {
return 400;
}
}
Well, you could try something like this:
location / {
if (condition_1) {
break;
}
if (condition_2) {
break;
}
...
if (condition_n) {
break;
}
return 400;
proxy_pass http://backend;
}
If any of condition_1, ... condition_n match, break keyword prevent return 400 and request goes to proxy_pass. If all conditions fail return 400 will make nginx to response 400 Bad Request error.
Conditions could be anything that if supports. E.g. if ($args_pass = 1) or if ($http_user_agent ~ MSIE), etc.