mod_rewrite: match string within URL, which regex to chose? - regex

I would like to use mod_rewrite to capture a string within brackets in my URL and do a redirect.
My URL:
something?var_a=A&var_b=(B)&var_c=C
my .httaccess file with the regex:
RewriteEngine on
RewriteRule ^/?.+var_b=\((.*)\)$ somedir/$1 [R]
I just would like to capture what's in between the round brackets, so my redirect should look something like this: somedir/B
I test my regex at http://htaccess.madewithlove.be/ but I get no match.
I don't know what I am missing here, even if I try much simpler regexes, e.g. .+var_b(.*)$ I get no match. Only if my regex was looking for a pattern at the beginning, I get a match, so for example the regex something(.*)$ works.
What am I missing here?

RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)var_b=\((.*?)\)(&|$) [NC]
RewriteRule ^.*$ somedir/%2? [R]
The reason is that RewriteRule does not receive the ?x=y part of the query. The %2 variable refers to the pattern from the last RewriteCond, while $2 would refer to the pattern from this RewriteRule. The ? at the end prevents the query part ?x=y from being automatically appended at the end of the result.
The (^|&) and (&|$) in the pattern guarantee that var_b=(B) is the complete parameter and not a part of it. Without these, the pattern would also match ?xyzvar_b=(B) or ?var_b=(B)xyz. With these, it will only match ?var_b=(B) or ?a=b&var_b=(B)&x=z etc.

Related

How do I find the 20th regex match group?

I am doing a rewriterule inside of my .htacess folder in one of my htdocs folders.
The rewriterule looks something like this:
RewriteRule ^index/(blah)/(blah2)/(blah3)..../(blah20)
^^^The above code looks like bad practice--don't worry about that.
Anyways, I heard before that ${20} was the correct way to access the 20th match group in regex, but even though in regex101 my 20th match group is matching blah20, whenever I print out the 20th capture group, I just get ${20}.
Why is this? Am I correctly accessing two digit match groups?
Edit--real rewriterule:
RewriteRule ^a/([\d]*)/(b/([\d]{2}:[\d]{2}:[\d]{2})/?)?(c/(\w*)/?)?(d/([\w]
{6})/?)?(e/([\w]{6})/?)?(f/([\w]{6})/?)?(g/([\w]{6})/?)?(h/([\w]{6})/?)?
(i/([\w]{6})/?)?(j/([\w]{6})/?)?(k/([\w]{6})/?)?(l/([\w]{6})/?)?(m/([\w]
{6})/?)? /index.php?a=$1&b=$3&c=$5&d=$7&e=$9&f=${11}&g=${13}&h=${15}&i=${17}&
j=${19}&k=${21}&l=${23}&m=${25} [L]
You cannot use back-reference number greater than 9 as per official mod_rewrite documentation.
From Manual:
RewriteRule back-references: These are back-references of the form $N (0 <= N <= 9). $1 to $9 provide access to the grouped parts (in parentheses) of the pattern, from the RewriteRule which is subject to the current set of RewriteCond conditions. $0 provides access to the whole string matched by that pattern.
If you are dealing with so many back-references then it is better to pass full URI after index/ to index.php and use explode inside the php code:
RewriteRule ^index/(.+)$ index.php?q=$1 [L,QSA,NC]
For example like this:
RewriteRule \^index(?:\/\w+){5}\/(blah6)
Will match 6th folder in the url.

Htaccess regex to exclude everything except one string

I have done this: http://rubular.com/r/AHI15Tb4ju, and it match the second url (http://gamempire.localhost.it/news/tomb-pc), but I want to exclude that url and match everything that do not have the word "news/" inside (but at the same time end in the way that I have specified).
How to do that?
Basically, i want to match only the third url (http://gamempire.localhost.it/tomb-pc).
Thanks!
You can use a rule like this:
RewriteEngine On
RewriteCond %{REQUEST_URI} !/news/
RewriteRule -(?:pc|ps2|ps3|ps4|xbox-360|xbox-one|xbox|wii-u|wii|psp|ps-vita|ds|3ds|iphone|ipad|android|playstation)(.*)$ / [L,R]
Since I didn't know any action part I just redirected these matching URI patterns to / that you can change according to your need.
Try using this:
^((?!news).)*-(?:pc|ps2|ps3|ps4|xbox-360|xbox-one|xbox|wii-u|wii|psp|ps-vita|ds|3ds|iphone|ipad|android|playstation)(.*)$
It should be noted that I tried to modify your original pattern as little as possible, assuming you also needed the (.*) at the end even though it appears that this is unnecessary for your purposes, and would match strings such as
"http://gamempire.localhost-pc.it/tomb" and "http://-pcgamempire.localhost.it/tomb".

mod_rewrite rule using date regex

I'm trying to write a rule that when user types in this url:
domain.com/09/13/2013/thisIsMyPageTitle
That url stays in browser window, but content from this url is displayed:
domain.com/contentlibrary/thisIsMyPageTitle
This is my rule that I currently get an error with:
RewriteEngine On
RewriteRule ^((0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d[/])$(.*) /contentlibrary/$1 [L]
I'm trying to match the date with regular expression, and use the (.*) from the initial url in the second one that holds the content and actually exists.
If you're not going to do anything with date then why bother being precise with date semantics. You can simplify your regex:
RewriteRule ^[0-9]+/[0-9]+/[0-9]+/([^/]+)/?$ /contentlibrary/$1 [L]
The error that you're getting is probably because you have unescaped spaces in your regex. Specifically these:
[- /.]
The spaces get interpreted by mod_rewrite as the delimiter between parameters. Additionally, you have this:
$(.*)
at the end of your pattern. The $ matches the end of the string, so you want those swapped:
(.*)$
So:
^((0[1-9]|1[012])[-\ /.](0[1-9]|[12][0-9]|3[01])[-\ /.](19|20)\d\d[/])(.*)$
shold be the pattern that you want.

mod_rewrite regexp

I'm working on some rewrite rules, and for some reason a regexp I'm not expecting to pass (and does pass not on any of my regexp testers) is passing in mod_rewrite.
The URL in question is:
http://url.com/api/projects.json?division=aa
And the rewrite rule is:
RewriteEngine On
RewriteBase /
RewriteRule ^api\/([^.?#/%\s]+)\.([^#?\s]+)$ api.php?type=$1&format=$2 [NC,L]
Because the second capture is immediately followed by $ I'd expect that URL to fail because of the query string, but it seems to accept just fine and pass the two parameters to GET.
Any thoughts?
Note: Query String
The Pattern will not be matched
against the query string. Instead, you
must use a RewriteCond with the
%{QUERY_STRING} variable.
Snip from the bottom of the docs

RewriteCond match for certain Query param/value pair

I have to do a redirect to another host if a certain parameter/value pair is in the querystring.
So far I have
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} [&\?]abc=23&?
RewriteRule ^(.*)$ http://anotherserver.com/$1 [R,NC,L]
that works for:
/index.php?id=95&abc=23
/index.php?abc=23&id=95
/index.php?id=95&abc=23&bla=123
but it also matches /index.php?id=95&abc=234 for example.
I need a pattern that matches exactly abc=23, no matter where it occurs.
Any suggestions on this? :-)
I'd try this regex (&|^)abc=23(&|$) and match is only against %{QUERY_STRING}.
The question mark makes the preceding token in the regular expression optional. E.g.: colou?r matches colour or color.
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} [&\?]abc=23&?
You are matching abc=23& OR abc=23 with the rest of the string unconstrained so abc=234 is a valid match. What you really want is & or nothing else. I'm not sure if this RegExp is legal in Apache but it would be written as:
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} [&\?]abc=23(&|$)
Here are the test cases I used at my favourite online RegExp tester:
abc=23&def=123
abc=234
abc=23