NGINX Regex location - Starts with X AND does not contain Y - regex

I have the following location config:
location ~ ^/(trucks|cars|planes|system|tools) {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/htauth_file;
proxy_set_header Host "server.lan";
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:8080$request_uri;
}
When anyone makes requests to
/trucks
or
/cars
etc, I want them to be authenticated by the basic auth. But when anyone makes requests to
/trucks?id=123
or
/cars?id=124
then I want no authentication, taken care of a lower location block.
I basically dont want the location to match when there is a question mark in the URI.
Is there a way to modify my pasted config so that it does not match when there is a question mark in the URI?

I suggest the following regex:
^/(trucks|cars|planes|system|tools)(?![^\s?]*\?)
DEMO.

Try following regex:
location ~ ^/[^?]+ {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/htauth_file;
proxy_set_header Host "server.lan";
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:8080$request_uri;
}
It will:
/cars <--match
/trucks <--match
/trucks?id=123 <-- no match

Related

Django Rest Framework deployed under subdirectory proxy urlpattern missmatch

I'm trying to deploy a small API using a subdirectory on the server. Usually if I do the following config it works fine:
location /iframe/api/ {
proxy_pass http://127.0.0.1:8001;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
client_max_body_size 0;
}
The funny thing is that for static files it seems to work, because I get back proper styling for the rest framework, but for every single urlpattern it also transfers the iframe/api which isn't ideal and basically not a single API route is matched.
I tried to add proxy_redirect off but still no avail. Any idea why isn't this working as expected? How should I deploy a rest framework API under a sub-directory?
Also tried to use FORCE_SCRIPT_NAME='/iframe/api', however I still get the same issue that the URL isn't matched The current path, iframe/api/, didn’t match any of these.
After quite a few hours spend debugging I was able to solve it kinda, but it required multiple ways to do it. If you have better solution feel free to post it!
First you need the trailing / for proxy_pass so the /iframe/api isn't transfered.
location /iframe/api/ {
proxy_pass http://127.0.0.1:8001/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
client_max_body_size 0;
}
This solved that part that the URLs wasn't being matched. For some strange reason I wasn't able to solve the static file sharing directly trough the reverse proxy, so what I ended up was to bind both media and static files to a volume on the main machine and serve them with alias
location /media {
alias /home/user/path_to_media/media;
try_files $uri $uri/ =404;
}
location /static {
alias /home/user/path_to_media/static;
try_files $uri $uri/ =404;
}
You also need to set the FORCE_SCRIPT_NAME in the settings file otherwise the urls generated by the rest framework won't work properly.

NGINX - Regex into locations.conf doesn't work

I have an issue into the configuration of my nginx proxy.
I just try to use regex has it is defined here: https://underthehood.meltwater.com/blog/2017/12/12/lightweight-tests-for-your-nginx-api-gateway/
But nothing works. My server won't start if it is any regex into the path.
I tried:
location ~ ^/tesla/(?<id>.*)$ {
proxy_pass http://localhost:8081/;
proxy_set_header Host $host;
}
or
location ~ ^/tesla/test/ {
proxy_pass http://localhost:8081/;
proxy_set_header Host $host;
}
or
location ~* ^/tesla/test/ {
proxy_pass http://localhost:8081/;
proxy_set_header Host $host;
}
Nothing work. My final aim is to extract a value from the url and do the following thing:
location ~* ^/(<version>.*)/test/ {
proxy_pass http://localhost:8081/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Prefix $version;
}
UPDATE (SOLVED)
I finally succeed thanks to Richard.
Here is the complete code:
location ~* ^/api/(?<version>.*)/(?<service>.*)(/.*/.*)$ {
proxy_pass http://$service.localnetwork:8080$3;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Prefix /api/$version/$service;
proxy_set_header msvc_name $service;
proxy_set_header msvc_version $version;
}
You can't use a proxy_pass with a static URI within a regular expression location block, it will throw an error - see your Nginx error log. See this document for details.
However, you can construct the URI to send upstream by appending variables to the proxy_pass statement. In your case, you could capture the remainder of the URI in the same regular expression.
For example:
location ~* ^/([^/]+)/test(/.*)$ {
proxy_pass http://localhost:8081$2;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Prefix $1;
}

NGINX / Location with regex

I wish that every request in the following format: /files/(whatever..)/(1 or 2 or 3) will go to the files_1 upstream with the /(whatevet) command. If the url is in the following format /files/(whatever..)/(4 or 5 or 6), it will go to the files_2 upstream with the /(whatevet) command.
Here is my location file:
location ~ "^/files/(.*)/[123]/" {
rewrite ^/files/(.*)/(.*) /$1 break;
proxy_pass http://files_1 ;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
}
location ~ "^/files/(.*)/[456]/" {
rewrite ^/files/(.*)/(.*) /$1 break;
proxy_pass http://files_2 ;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
}
When I check the logs, It doesn't do the redirection with the command /files/save/2/ (which should go to files_1 upstream with the command: /save)
How can I do it?
It's possible that you have another location / block that is redirecting /files/save/2 to /files/save/2/ because the former does not match your current location blocks.
You could eliminate the captures on the rewrite by using a named capture in the location regex, like this:
location ~ "^/files(?<command>.+)/[123]/" {
rewrite ^ $command break;
...
}
Alternatively, correct the rewrite directive so that only the command is extracted:
rewrite ^/files(.+)/\d/ $1 break;
or:
rewrite ^/files/([^/]+)/ /$1 break;

Nginx: location regex not working

i'm getting trouble with my regex don't know what is wrong with it. it's returning a URi with orls/f instead of orls/f?p=4550. When i pass https://secure.toto02.com/orls/myservice/f?p=4550
my conf file is below
location ~ "^/([a-zA-Z]+)/myservice/(.+)$" {
error_log /var/log/nginx/error-server.log notice;
rewrite_log on;
#proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://192.168.3.45:8080/orls/$2;
proxy_redirect http://192.168.3.45:8080/orls/ https://secure.toto02.com/$1/myservice/ ;
}
Can anyone help?
Capturing the location will not encompass the query string. You have to manually include it via $is_args and $args variables like so:
proxy_pass http://192.168.3.45:8080/orls/$2$is_args$args;

nginx location regex /yyyy/mm/dd/

I'm trying to pass requests from address helpme,com/donor/2014/12/07/Name on the other server.
URL like the: /donor/2014/12/07/Mike
need to convert to a query type of: /donor.php?yyyy=2014&mm=12&dd=07&donor=Name.
Now i have:
location ~* ^/donor/+$ {
rewrite ^/(.*) /donor.php?yyyy=$1&mm=$2&dd=$3&donor=$4 break;
proxy_pass http://164,151,234,168;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Help me please.
The regex for that should be (untested) something like /donor/(\d{4})/(\d{2})/(\d{2})/(.+).
The use of commas (,) instead of periods (.) for the hostname/IP seems wrong, though. As far as I know the same character is used everywhere….