Nginx location group capture + rewrite - nginx

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.

Related

How to rewrite url for url with multiple query parameter?

Server: Nginx
Application: PHP
URL in question is
/p/all_articles/user/ABC
/p/all_articles/user/ABC/page/123
which is
/index.php?p=all_articles&user=ABC
/index.php?p=all_articles&user=ABC&page=123
ABC = this could be a-zA-Z0-9 as it's username
123 = this could be page numbers 0-9
Tried many combinations and options, the following got me much closer to expected result, but it is not perfect.
location /p/all_articles {
rewrite ^/p/all_articles/user/(.*)?$ /index.php?p=all_articles&user=$1 last;
rewrite ^/p/all_articles/user/(.*)/page(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&page=$2 last;
try_files $uri $uri/ /index.php;
}
the above rewrite location block results only when one of them is quoted other one would work, but not together.
Similarly
/search/QUERY
/search/QUERY/page/123
which is
/index.php?search=QUERY
/index.php?search=QUERY&page=123
QUERY = anything a-zA-Z0-9 and space
123 = this could be page numbers 0-9
like the one for all_articles, the closest I was able to get is
location /search {
rewrite ^/search /index.php?search last;
rewrite ^/search/(.*)/page(?:/([0-9]+))?$ /index.php?search=$1&page=$2 last;
try_files $uri $uri/ /index.php;
}
But, this works to get either one of the clean URL when the other rewrite is quoted, but not together.
I appreciate if anyone give any answers to solve this issue.
The rewrite statements are evaluated in order so the more specific regular expression needs to be placed before a less specific regular expression.
With the two regular expressions:
^/search
^/search/(.*)/page(?:/([0-9]+))?$
The first one will match anything that also matches the second, so the second regular expression will never be evaluated.
The simple solution is to reverse the order of the rewrite statements in both of your location blocks.

Case insensitivity in nginx

We have several SEO pages like:
http://www.example.com/PageOne.html
Which we redirect in config like:
location = /PageOne.html {
rewrite ^/(.*) /seo.php?id=1 last;
}
Problem is if a user access this page by typing:
http://www.example.com/pageone.html
"Page Not Found" error is displaying. There are approximate 500+ seo pages. How to write rule for nginx to ignore case sensitivity in url? I want a common solution for all url.
Specifically for PageOne.html, you can do the following:
location ~ /PageOne.html {
return 301 http://www.example.com/pageone.html$1;
}
If you have multiple URIs which need to be redirected, it appears the best option is to use Perl:
location ~ [A-Z] {
perl 'sub { my $r = shift; $r->internal_redirect(lc($r->uri)); }';
}
If you have hundreds of unique URIs which would involve many location blocks as above, I'd consider changing your application to handle lowercase URIs rather than expecting the webserver to handle the lowercase conversion.
This solved my issue. Sad to say that there is not many articles related to these issues, even nginx doesn't provide user friendly Help/Tutorials.
location ~* ^/-PageOne.html {
rewrite ^ /seo.php?page_id=1 last;
}
Hope this helps!

Nginx rewrite to css factory

I have a rule which is not working correctly.
I need it so that whenever URL xxx.com/forum/css.php is hit, it is re-written to xxx.com/forum/core/css.php.
I have written the following location block for it:
location ~^ /forum/css.php {
rewrite ^ /forum/core/css.php permanent;
}
Also needing to be taken into account is that the file is a factory so it accepts parameters, the url being hit actually looks like xxx.com/forum/css.php?x=123&y=string. Will this also be taken into account in the re-writes or does it need to be specified? Sorry if the question seems silly I am just beginning to work with servers! Thanks fellow coders!
To rewrite a single URI (with or without query string) you could use a location =:
location = /forum/css.php {
rewrite ^ /forum/core/css.php permanent;
}
The rewrite directive appends the query string (unless terminated with ?). See this and this for more.

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.

Having issues with regex matching wrong URLs in NGINX rewrite

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

Resources