Suppose I have these paths:
/
/something # this path is variable (any characters except /)
/api/v1/something
What is the best nginx config to capture this requirement? The following is not working for m:
server {
listen 8080;
location ~^/(?:.*)$ {
...
}
location / {
...
}
location /api/v1/something {
...
}
}
Your regular expression matches everything which means it always wins! See the documentation to understand how Nginx chooses which location block to process a request.
You do not need to use a regular expression location.
First define location blocks for the single URIs using the = operator:
location = / { ... }
location = /api/v1/foo { ... }
Then use the default location to catch anything else:
location / { ... }
The above location blocks can appear in any order. Only regular expressions are sensitive to evaluation order.
Related
I have a location block that works when I am not using a regex.
location ^~ /mapdata/ {
alias /data/map/coordinates/;
}
When i visit http://localhost/mapdata/2002/g.txt I am getting the data from the file.
When I alter the location and use a regex. I can not read the file, the location block is correct. But the url gets an extra slash added on to the end http://localhost/mapdata/2002/g.txt changes to http://localhost/mapdata/2002/g.txt/
location ~ "^/mapdata/([\d]{4})/.*.txt$" {
alias /data/map/coordinates/;
}
alias inside a regular expression location requires the full path to the file to be captured. See the documentation for details.
For example:
location ~ "^/mapdata/([\d]{4}/.*\.txt)$" {
alias /data/map/coordinates/$1;
}
Those are my two nginx rules :
rewrite ^(/v1/foobar)(.*)$ /final$2 permanent;
rewrite ^(/v1/foobar-tow)(.*)$ /final$2 permanent;
I expect that /v1/foobar-two/foo will use the second rule and then will redirect to /final/foo but I doesn't : since the URL starts with foobar, the first rule will be used and finally will redirect to final-two/foo : the concatenation of the first target and the difference between the first and second rule !
To solve the problem I've just inversed the rules, but I wonder if there is a better solution !
To sum up, this is what I'm looking for :
/v1/foobar -> /final
/v1/foobar/hello -> /final/hello
/v1/foobar-tow -> /final
/v1/foobar-tow/hola -> /final/hola
To avoid surprises with NGINX, and increase configuration scalability, you should, generally:
try to live without rewrite directive; as per NGINX author it simply appeared before location and in many cases you can now use location with capture groups in lieu of rewrite
design your regular expressions in the way that the order of matching is not important, if possible
use exact matching, where applicable
isolate regular expression locations under a prefixed one
Putting all things together:
location /v1/ {
location = /v1/foobar {
return 301 /final;
}
location ~ ^/v1/foobar/(\w+)$ {
return 301 /final/$1;
}
location = /v1/foobar-tow {
return 301 /final;
}
location ~ ^/v1/foobar-tow/(\w+)$ {
return 301 /final/$1;
}
}
We are trying to create a location rule on nginx side, but its not working as expected. Below is the location rule
location ~* ".*\.legalcontent\.html\?path=\/legal\/.*" {
return 200 'regex rule'; //Using this temporarily to confirm if rule is triggering
}
Incoming URL is below, want to capture (.legalcontent.html?path=/legal/)
https://www.mycompany.com/myapp/myproduct/mysubpage.legalcontent.html?path=/legal/somepage
Tested regex separately on regex tool, seems to be good
But its not working, tried simple context roots to check if everything else is good.
# Following simple rules works fine, but we want location to kick-in
# only for specific condition
location /myapp {
return 200 'myapp rule';
}
location /myapp/myproduct {
return 200 'myapp myproduct rule';
}
Is there a way to handle location rule for this kind of input URL
The location will only check the path of the request. To check the arguments you must create a conditional with the $args variable.
location ~* ".*\.legalcontent\.html$" {
if ($args ~* "^path=\/legal\/.*") {
return 200 'regex rule';
}
}
I want to create a nginx localtion do to the following
Given URL:
example.com/foo/bar/123456?ItemID=123456&aid=0&bid=0
Task:
If both numbers are the same and aid and bid are zero, then rewreite the url to example.com/foo/bar/123456
My Try:
location ~ ^/foo/bar/(?<prid>\d+)\?ItemID=\1&aid=0&bid=0$ {
rewrite ^ /foo/bar/$prid? permanent;
}
But that doesn't work. ;)
Would be great if s.o. could give me a hint.
EDIT:
nginx seems not to match GET-Parameters by regex at all (in location line) so you have to use $args and check with if (which can be evil according to documentation).
This should work:
location ~ /foo/bar/(\d+) {
if ($arg_ItemID = $1) { set $check I; }
if ($arg_aid = 0) { set $check "${check}A"; }
if ($arg_bid = 0) { set $check "${check}B"; }
if ($check = IAB) {
rewrite ^ /foo/bar/$arg_ItemID? permanent;
} }
Explanation:
nginx doesn't include the parameters in the match for rewrite. You can access the parameters by name via $arg_name.
the set of if-statements is a work-around (described here), because nginx doesn't allow multiple conditions
the ? at the end of the replacement cuts off the arguments from the original request
I can't figure out how to configure the check whether $remote_user equals to the first part of the location.
location / {
auth_basic "ElasticSearch";
auth_basic_user_file /etc/nginx/search_passwords;
location ~/([^/]*)/ { # named capture did not work either
if ($remote_user = $1) { # ERROR: Unknown variable: $1 / $NAMEDWHATEVER
break;
}
}
}
My use-case:
I am trying to "secure" an ElasticSearch-Cluster by using a nginx-reverse proxy for authentication. I want to allow multiple users, but the modifications for a new user should be as simple as possible; best case - just change the htpasswd-file.
I'm trying to adopt the nginx-elasticsearch-proxy but fail to check whether remote_name and index-name are equal.
It should be possible and you can also define a name of a variable when matching with regex.
Here in the code fragment below, I assign the result of the regex to the variable $username. Then I can check it and if matching the $remote_user (be sure that this one is correctly set, in case just debug it as I did) then I added an extra header to the response so you can see it with the Firebug network console or just by using the curl command .
Have a look to see if this one helps you.
location / {
auth_basic "ElasticSearch";
auth_basic_user_file /etc/nginx/search_passwords;
location ~ /(?<username>([^/]*))/ { # capture and store in the username variable
if ($remote_user = $username ) {
add_header 'matched' 'true $username';
break;
}
}
}
See also this How to I get variables from location in nginx? for more info.