mod_rewrite RewriteRule anomaly - regex

I'm preparing rewrite rules for my site. And I'm faced problem when target URL contains characters like "%3A".
Apache mod_rewrite just removes "%3" when rewrites url.
For example I need rewrite url
/primed-white-mdf-skirting+architrave/
to
/Products/Decorating+Interiors/Mouldings/Skirting/c/1000589?q=%3AtopSellers%3AColour%3AWhite&text=#
I have generated rule for this. Here it is:
RewriteRule ^primed-white-mdf-skirting\+architrave/ /Products/Decorating+Interiors/Mouldings/Skirting/c/1000589?q=%3AtopSellers%3AColour%3AWhite&text=# [R=301,L,NE]
So rewrite pass to:
/Products/Decorating+Interiors/Mouldings/Skirting/c/1000589?q=AtopSellersAColourAWhite&text=%23
Why this happens? Please help

You need to escape the % otherwise %3 is considered a back-reference of captured group from RewriteCond:
RewriteRule ^primed-white-mdf-skirting\+architrave/ /Products/Decorating+Interiors/Mouldings/Skirting/c/1000589?q=\%3AtopSellers\%3AColour\%3AWhite&text=# [R=301,L,NE,QSA,NC]

Related

How to write expression to grab all after an expression and then rewrite in htaccess

I'm new to the rewriting of urls and regex in general. I'm trying to rewrite a URL to make it a 'pretty url'
The original URL was
/localhost/house/category.php?cat=lounge&page=1
I want the new url to look like this:
/localhost/house/category?lounge&page=1
(like I say, I'm new so not trying to take it too far at the moment)
the closest I've managed to get it to is this:
RewriteRule ^category/(.*)$ ./category.php?cat=$1 [NC,L]
but that copies the whole URL and creates:
/localhost/house/category/house/category/lounge&page=1
I'm sure, there must be an easy way to say copy all after that expression, but I haven't managed to get there yet.
I will try to help you:
You probably have already, but try a mod rewrite generator and htaccess tester.
From this answer: The query (everything after the ?) is not part of the URL path and cannot be passed through or processed by RewriteRule directive without using [QSA].
I propose using RewriteCond and using %1 instead of $1 for query string matches as opposed to doing it all in RewriteRule.
For your solution, try:
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^house/category$ house/category.php?cat=%1 [NC,L]
This will insert the .php and cat= while retaining the &page=
Anticipating your next step, the below mod rewrite may help get started in converting
http://localhost/house/category/lounge/1
to
http://localhost/house/category.php?cat=lounge&page=1
Only RewriteRule necessary here, no query string:
RewriteRule ^house/category/([^/]*)/([0-9]*)/?$ house/category.php?cat=$1&page=$2 [NC,L]
Use regex101 for more help and detailed description on what these regexes do.
If it still not working, continue to make the regex more lenient until it matches correctly:
Try to remove the ^ in RewriteRule so it becomes
RewriteRule category$ category.php?cat=%1 [NC,L]
Then it will match that page at any directory level. Then add back in house/ and add /? wherever an optional leading/trailing slash may cause a problem, etc.
Thanks for all your suggestions, I took it back to this
RewriteRule category/([^/])/([0-9])/?$ category.php?cat=$1&page=$2 [NC,L]
which has done the trick, and I'll leave it at this for now.

htaccess regex to find image and image number

I have such a url:
/keyword1/keyword2/slugged-title-8286-1.jpg?wx=292&hx=164
I would like to forward in this case to:
/images/8286-1.jpg?wx=292&hx=164
the listing number (here 8286) can be 4 or 5 digits and could perhaps contain letters. Also the parameters after ? could be different.
Could you please help me to get this solved?
I haven't done a lot with regex and not sure how this can be done.
You can use this rule in your site root .htaccess:
RewriteEngine On
RewriteRule -(\w+(?:-\d+)?\.jpe?g)$ /images/$1 [L,NE,R=302]
If you don't want a full redirect then use:
RewriteRule -(\w+(?:-\d+)?\.jpe?g)$ /images/$1 [L]
QUERY_STRING is automatically carried over to target URL.

.htaccess redirect is sending whole string, instead of partial

I partially have my .htaccess rule working. What I have currently is:
#tag to search redirect
RewriteCond %{REQUEST_URI} ^/tag\/*
RewriteRule ^(.*) https://www.testurl.co.uk/search-results?hsf=$1&id=12 [R=301,L]
What is currently happening, is where the $1 is, the entire of tag/* is going in there.
i.e request is tag/test URL generated is
https://www.testurl.co.uk/search-results?hsf=tag/test&id=12
when it should ideally be:
https://www.testurl.co.uk/search-results?hsf=test&id=12
Any help would be greatly appreciated.
Many thanks
You can use this rule:
RewriteRule ^tag/(.+)$ https://www.testurl.co.uk/search-results?hsf=$1&id=12 [R=301,L,QSA]
Pattern ^tag/(.+)$ will capture any value after /tag/ into group #1 and that is being used in $1.
Make sure to clear your browser cache before testing this.

Correct way to redirect url to specific language with parameter at the end of the url

What I would need is to redirect with htaccess an url that has already some google analytics parameters in it, and redirect it adding the language parameter at the end of the url. I tried this with no luck so far but I know its wrong at some point:
RewriteCond %{HTTP:Accept-Language} ^fr [NC]
RewriteRule ^random?$1 http://www.domain.com/random?$1&language=french [R=301,QSA]
I'm trying with $1, I don't know if this is correct, the intention of which is to include all the parameters like utm_source=1&utm_medium=2, after this I would need to include the language parameter, so redirected url should look like http://www.domain.com/random?utm_source=1&utm_medium=2&language=french.
What is the right way to achieve what I need?
Thank you in advance.
Back-References
In your rule, $1 is a back-reference to a capture group that doesn't yet exist.
Try this instead:
RewriteCond %{HTTP:Accept-Language} ^fr [NC]
RewriteCond %{QUERY_STRING} !^.*language=french
RewriteRule ^(random.*) $1?language=french [R=301,QSA,L]
At the beginning ^ of the url path, (random.*) matches random and the rest of the url. (So we are only rewriting urls that start with random... is that what you want?)
We rewrite with the back-reference $1, followed by the query string ?language=french
The QSA flag ensures that existing query-string parameters are added.

ExpressionEngine RewriteRule RegEx Throws 500 Error

When using categories in ExpressionEngine, a Category URL Indicator trigger word can be set to load a category by its {category_url_title}.
I would like to remove the category "trigger word" from the URL.
Here is what I have so far, with the trigger word set to "category":
RewriteRule /products/(.+)$ /products/category/$1 [QSA,L]
I'm not an expert at writing regular expressions, but I do a little. I'm 99% sure my RegEx is fine, however when trying to use it as a RewriteRule in my .htaccess file, I'm getting a 500 error.
I'm sure it's something stupid, but for some reason I'm not seeing my mistake. What am I doing wrong?
Update: Adding a ^ to the beginning of the RewriteRule fixed the 500 error.
RewriteRule ^/products/(.+)$ /products/category/$1 [QSA,L]
This is not safe. Take:
/products/a
The regex group matches a.
It will be rewritten to:
/products/category/a
which the regex matches again (this time, the group matches category/a). Guess what will happen.
You want /products/ from the beginning of input if it is not followed by category/, which means you want a negative lookahead. Also, the QSA flag is of no use, you don't have a query string to rewrite (QSA stands for Query String Append):
RewriteRule ^/products/(?!category/)(.+) /products/category/$1 [L]
Another way to use it (and which I personally prefer) is to use a RewriteCond prior to the rule:
RewriteCond %{REQUEST_URI} ^/products/(?!category/)
RewriteRule ^/products/(.*) /products/category/$1 [L]
This Apache RewriteRule should do the job for you*:
RewriteCond %{REQUEST_URI} ^/products/(?!category/)
RewriteRule ^/products/(.*) /products/category/$1 [L]
With this in place, you'll need to hard code your category links manually:
{categories backspace="2"}
{category_name},
{/categories}
Which would output the new Category URLs you desire:
http://example.com/products/toys
Otherwise, if using the recommended path variable when building your category links:
{categories backspace="2"}
{category_name},
{/categories}
Would create links with the Category URL Indicator in the URI:
http://example.com/products/C1
http://example.com/products/category/toys
Which — while perfectly valid — would create canonicalization issues on your site since the different URLs would appear as duplicate content to search engines.
*Credit to fge for brilliant mod_write rule.