Having issues with regex matching wrong URLs in NGINX rewrite - nginx

Hi I have urls that look like this
http://dansawesomesite.com/123/articlename
I have the following rewrite rule in nginx
location ~* /(\d+)/([\+\w-\ ]+)/?$ {
try_files $uri /wpcontentredir.php?slug=$1;
}
This matches the above URL however the issue comes about when I have the following URL's
http://dansawesomesite.com/posts/630325/like
(as well as a number of similar)
These also end up getting matched which is correct based on my regex, but will mess things up as I dont want these urls parsed through that try_files, I just want them to pass as is.
Just wondering if anyone can help me with only matching the top first URL?
CHeers
Dan

Try to add "^" to the beginning of regexp
location ~* ^/(\d+)/([+\w-\ ]+)/?$
So it will match only if first part of URI contains digits and not "posts" or something

Related

Redirect URI on NGINX

I have a page on my site (only accessible to logged in users), that looks like the following:
https://www.example.com/forum/new
However, sometimes when users click or refresh they get the page as follows:
https://www.example.com/forum%252fnew
Now %25 decodes to the % symbol, and %2f decodes to the "/", so it seems the URI is getting double-encoded.
I'm not sure how this encoding is happening, but I thought a workaround would be to have Nginx redirect back to the correct URL, with something like the following:
location ~ /forum%252Fnew {
return 301 https://www.example.com/forum/new;
}
I have tried escaping the % in the location with \, but neither seem to be working.
What am I missing?
The URI has been decoded and normalized before being processed by the location and rewrite directives, so the %25 looks like a single %.
The example in your question shows a regular expression location statement. The ~ operator is for case-dependent matching, whereas the ~* operator is for case-independent matching.
To make the example in your question work, you will need to change it to:
location ~* /forum%2Fnew
Or:
location ~ /forum%2fnew
See this document for details.

Nginx image not found fallback

My site have many images /image/test/manyfile.jpg and now day I have /image/test/manyfile_large.jpg, but not all .jpg have _large.jpg.
So my idea is use Nginx to check manyfile_large.jpg file, if not exist then rewrite or redirect to manyfile.jpg
Can anyone give an example config?
Thanks a lot! :)
You can use try_files to test for the existence of one or more files. See this document for details.
First you need to capture the components of the URI so that you can construct the two filename variants to try.
I am not sure if the examples in your question and comment are URIs or pathnames. In the following example, the URI is /image/foo/bar.jpg and the corresponding files are located at /path/to/image/foo/bar.jpg and (optional) /path/to/image/foo/bar_large.jpg.
For example:
location ~ ^(/image/.+)\.(jpg|png|svg)$ {
root /path/to;
try_files $1_large.$2 $1.$2 =404;
}
The block will return the large variant if it exists, then the regular variant if it exists, then a 404 status if neither exist.
The order of regular expression location blocks is significant, as the first block with a matching regular expression is used to process the request. See this document for details.

Nginx location group capture + rewrite

I'm trying to do a group capture in a Nginx location block and it's not working for me.
Is what I am trying to do even possible?
location ~* /(?<cat>cars|trucks|bikes|motorcycle|quads) {
rewrite ^/$cat/([0-9]+)(.*)$ /page.php?id=$1 last;
}
The error message I am receiving is :
"^/$cat/([0-9]+)(.*)$" does not match "/cars/120/new-car-rentals/"
I have a lot more categories than what I am posting, and trying to prevent writing a rewrite 5x for each specific category name.
Any help would be appreciated.
I'm not familiar with this particular syntax, but based on my experience with others, is it possible that you simply need to escape the forward slashes you're using?
location ~* \/(?<cat>cars|trucks|bikes|motorcycle|quads) {
rewrite ^\/$cat\/([0-9]+)(.*)$ /page.php?id=$1 last;
}
Note the named capture in the location regex: if you want to use a value captured here, you must use the named syntax (?<name>), numbers do not work.
I solved the issue by doing this instead :
location ~* /(cars|trucks|bikes|motorcycle|quad-bikes) {
rewrite ^/([a-zA-Z-]+)/([0-9]+)(.*)$ /page.php?id=$2 last;
...
...
}
The regex ([a-zA-Z-]+) allows me to use characters a-z (case insensitive) with possible dashes in my category / page names.

Nginx rewrite anything after specific keyword

I want to rewrite all requests after "whois" keyword in url to whois.php in nginx but can't find suitable rules.
e.g. rewrite domain.com/whois.php/TEST.COM to whois.php?domain=TEST.COM.
There are a number of options available to you. One solution is:
location ~* ^/whois.php/ {
rewrite ^(/whois.php)/(.*)$ $1?domain=$2 last;
}
Place the location block above other regex locations that might match, as regex locations are executed on the basis of the first one that matches.
See this and this for more.

Nginx rewrite with conditional destination

I have a site with two RESTful URL schemes:
foo.com/model/id and
foo.com/model/id/action
The actual pages served by these URLs are in the form of
$model.php?id=$id and
$model_$action.php?id=$id respectively.
I have a single regular expression that will match both cases ^(\w+)s/([A-z0-9]+)(?:/(\w+))?/?$ and I'd like to use a single Nginx rule to rewrite for both types of URLs, but I'm not sure how to do this. In pseudocode I imagine the rule would look something like this
rewrite ^(\w+)s/([A-z0-9]+)(?:/(\w+))?/?$ /(($3) ? $1_$3.php?$id=$2 : $1.php?$id=2)
This isn't valid syntax (so far as I know), but can something like this be done in Nginx?
Rewrite the possible urls in turn starting with the longest to the shortest to that overlapping matching strings, "/model/id" in this case, would be matched in the longer url string first.
location / {
# For "/model/id/action" to "$model_$action.php?id=$id"
rewrite ^/(.+)/(.+)/(.+)(/?)$ $1_$3.php?id=$2 last;
# For "/model/id" to "$model.php?id=$id"
rewrite ^/(.+)/(.+)(/?)$ $1.php?id=$2 last;
}
location ~ .+\.php$ {
# Handle PHP
}
The "(/?)" is just in case the urls sometimes come with an ending slash. If they never do, it can be removed. In this case, it will probably be best to specifically always add a closing slash and have "(/?)" as "/".

Resources