Passing a capture group in query parameters in NGINX URI - regex

In NGINX, is there any way to pass a capture group in a query parameter for a rewrite outside of a location block, such as this? Thanks!
if ($request_uri = /abc/def?query=(.*) {
rewrite ^.*$ /123/$1? permanent;
}

Below should work for you
if ($request_uri ~ "/abc/def\?query=") {
rewrite ^.*$ /123/$arg_query/? permanent;
}

Related

nginx match a folder in path and with no .html which needs to rewrite with .html appended

I have a URL which contains subfolders in the path and may or may not contain .html.
e.g.
https://www.example.com/store/test/en/test/ANYCATEGORY/ANDCATEGORY/OPTIONALCATEGORY/PROGRAMNAME/p/100002020
I want to match if the url contains "/p/" in the path AND there is no .html at the end.
If these conditions are met, I want to append with .html
e.g.
https://www.example.com/store/test/en/test/ANYCATEGORY/ANDCATEGORY/OPTIONALCATEGORY/PROGRAMNAME/p/100002020
I have tried with if statements and location but no luck with any of those.
This is what I have tried with no luck:
if ($uri ~ ^(.*)/p/(.*)$){
rewrite ^(.+)/$ $1.html permanent;
}
if ($uri ~ ^(.*)/p/(.*[^.html])$){
rewrite ^(.+)/$ $1.html permanent;
}
location ~ ^(.*)/p/(.*[^.html])$ {
rewrite ^(.+)/$ $1.html permanent;
}
You need a positive look ahead (?=.*\/p\/) for ensuring the presence of /p/ and a negative look ahead (?!.*\.html$) to ensure the string doesn't end with .html. The correct regex to use is this,
^(?=.*\/p\/)(?!.*\.html$).+$
Demo
Then try rewriting your if condition the way you were doing, which should be this,
location ~ ^(?=.*\/p\/)(?!.*\.html$).+$ {
rewrite ^(.+)/$ $1.html permanent;
}
Also, in your regex [^.html] this is a character negation and will only negate certain characters present in character set after ^ and for negating a sequence of characters, you need to use a negative look ahead pattern like I did in my regex.
location ~ ^(?=.*\/p\/)(?!.*\.html$).+$ {
try_files $uri $uri/ #rewrite;
}
location #rewrite {
rewrite ^(.+)$ $1.html permanent;
}

Nginx Replace Query string redirect

We were running on apache previously and used the below code to redirect/replace one of our query parameters.
RewriteCond %{QUERY_STRING} ^limit=(.*)$ [NC]
RewriteRule ^ %{REQUEST_URI}?product_list_limit=%1 [L,R=301]
This would successfully redirect the below URL
www.example.com/clothing.html?limit=all
TO
www.example.com/clothing.html?product_list_limit=all
I have used a htaccess redirect convertor that has produced the below. This doesn't work
location ~ / {
if ($query_string ~* "^limit=(.*)$"){
rewrite ^(.*)$ /$request_uri?product_list_limit=%1 redirect;
}
}
Any help appreciated
Thanks
You should not use $request_uri to construct the rewritten URI, as it also contains ?limit=all - so your rewritten URI would look like: /clothing.html?limit=all?product_list_limit=all
The rewrite statement resets numeric captures, so you will need to use a named capture in the if statement.
The URI without query string is available as $uri or as a capture from the rewrite statement's regular expression.
Either of these forms should work for you:
if ($query_string ~* "^limit=(?<limit>.*)$") {
rewrite ^(.*)$ $1?product_list_limit=$limit? redirect;
}
Note the trailing ? to prevent the original query string from being appended. See this document for more.
Or:
if ($query_string ~* "^limit=(.*)$") {
return 302 $uri?product_list_limit=$1;
}
The value of the limit argument is also available as $arg_limit, so you could also use this:
if ($arg_limit) {
return 302 $uri?product_list_limit=$arg_limit;
}
See this document for details.

Rewrite with 404 urls with nginx

I'm trying to rewrite some urls which are showing up as 404's but the I can't get the rewrite to work. The Urls look like this /ossobuco-alla-milanese​​/1451114854360.1451114854360?time=1451114851111. I would like to remove 1451114854360.1451114854360?time=1451114851111 with a rewrite.
In my nginx config I have the following rewrite rule
rewrite "^\/(.*)\/(\d{13}\.\d{13}\?time=\d{13})$" /$1/ permanent;
I tested the regex in 2 online regex tools regex101 and regex pal and it should work but the don't seem to work on my server.
To match query string use $args:
location / {
if ($args ~* "^time=\d+") {
set $args '';
rewrite "^/(.+)/\d+\.\d+/?$" /$1 permanent;
}
}
PS: If you want to match only 13digits.13digits then use:
rewrite "^/(.+)/\d{13}\.\d{13}/?$" /$1 permanent;
In the end its was just a really simple location block and the ? removes the args.
location ~* ^/(.+)/\d+\.\d+$ {
rewrite ^/(.+)/\d+\.\d+$ /$1? permanent;
}

Combine three nginx rewrites into one

Is it possible to rewrite this regular expression so it fits all my use-cases below?
location ~ \.mp3$ {
rewrite "^/(\d{4})/0(\d)/0(\d)/(.*).mp3$" /$1/$2/$3/$4.mp3 permanent;
rewrite "^/(\d{4})/0(\d)/(\d{1,2})/(.*).mp3$" /$1/$2/$3/$4.mp3 permanent;
rewrite "^/(\d{4})/(\d{1,2})/0(\d)/(.*).mp3$" /$1/$2/$3/$4.mp3 permanent;
}
Real URL: 2012/7/8/piper.mp3
Should match:
2012/7/8/piper.mp3
2012/07/8/piper.mp3
2012/7/08/piper.mp3
2012/07/08/piper.mp3
Thanks

nginx Rewrite Rules to Re-write Every Match Of a Certain Regex Except

I'm writing rewrite rules in nginx.
I want to rewrite every URI that matches /A/B[anything] to /X/ except /A/B/C[/].
How do I do this?
What I've tried:
if ($request_uri ~ ^/A/B/C/?) {
break;
}
rewrite ^/A/B /X/ permanent;
This rewrites /A/B to /X/, but /A/B[anything] doesn't get redirected, nor does /A/B/C/ stay at /A/B/C/.
rewrite ^/A/B/?$ /X/ permanent;
Should do it
I figured out the issue.
I needed to make the rewrite line
rewrite ^/A/B(.*)? /X/ permanent;
The (.*)? means " and optionally match anything any amount of times."