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
Related
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;
}
}
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.
How to extract only the name of file from a request?
I have URLs like these:
my_domain.com/dir1/image1.png
my_domain.com/dir1/image143.jpg
my_domain.com/dir1/image167658.gif
# [etc, images]
And these sections:
location / {
# [..........]
}
~ ^/dir1/.(jpg|png|gif) {
set $my_file_name $1;
# [...........]
}
1st issue: it won't trigger the 2nd section when I'm requesting one of the URLs mentioned above
If I change it to be:
/dir1 {
set $my_file_name $uri;
# [...........]
}
It'll trigger it, yes. However, in this case $my_file_name will contain the whole URL, whereas I need only the name of a file/image. For instance, image143.jpg
Question:
How should I change the section with /dir1 such that 1) it'll match the URLs from above and similar ones, and 2) I'll be able to extract a requested file or image name from a URL?
You need to use a regular expression with a capture.
For example:
location ~ ^/dir1/(?<filename>.*\.(jpg|png|gif))$ {
# do something with the $filename variable
}
See this document for details.
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';
}
}
Preset:
got a gallery script that is creating thumbnails like so:
GET /path/to/script/thumb.php?src=host.tld/path/to/file.jpg
Goal:
rewrite the hostname in src to a different name:
GET /path/to/script/thumb.php?src=newhost.tld/path/to/file.jpg
It's only the host that I need replaced, everything else should stay the same.
I've tried a couple of things but nothing produces the result that I want.
This is the code as it is now (not working):
location ~* thumb {
if ($args ~ "(src=http://host.tld:8080/)(.*)" ) {
set $params $2;
rewrite ^.*$ thumb.php?src=http://newhost.tld/$params? last;
}
}
also, host.tld could be just about anything so matching on host.tld literally is just a simplification for now.