Reference capture groups of multiple RewriteCond in RewriteRule - .htaccess

When I have multiple RewriteCond chained together, only the capture groups of the last RewriteCond can be referenced with %0-%9.
In the following problem the parameters in the query string of the url can be in any order. To parse them into a fancy url I would need to match each parameter in the query string individually:
RewriteCond %{QUERY_STRING} param1=([^&]+)
RewriteCond %{QUERY_STRING} param2=([^&]+)
RewriteCond %{QUERY_STRING} param3=([^&]+)
RewriteRule ^foo$ bar/%1/%2/%3/ [R]
Like I pointed out... this doesn't work. To fix this, I could reference the capture group of the previous RewriteCond in the next RewriteCond and 'propagate' each parameter to the actual RewriteRule:
RewriteCond %{QUERY_STRING} param1=([^&]+)
RewriteCond %1&%{QUERY_STRING} ^([^&]*)&.*param2=([^&]+)
RewriteCond %1&%2&%{QUERY_STRING} ^([^&]*)&([^&]*)&.*param3=([^&]+)
RewriteRule ^foo$ bar/%1/%2/%3/ [R]
This should work, but for each additional parameter it get's messier. An other solution could possibly be parsing one parameter and redirecting the client after each parameter (resulting in a lengthy chain of redirects, which I would like to avoid).
Is there an cleaner way of accessing the capture groups of all RewriteCond's in the RewriteRule (e.g. is it possible to name them or assign them to a variable so I can reference them somewhere else?)

You could try constructing the target URL inside the rewrite conditions:
RewriteCond ##%{QUERY_STRING} (.*)##(|.*&)param1=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param2=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param3=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param4=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param5=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param6=([^&]+)
RewriteRule ^foo$ /bar%1/%3? [L,R]
When I try to request:
/foo?param1=a&param2=b&param6=3&param3=4&param5=5&param4=6
I get redirected to:
/bar/a/b/4/6/5/3
Adding any additional required query string parameters won't make it look any more messy than it already is.

After experimenting some more, it would be possible to parse all parameters as environment variables and use them like that. I doubt it is very efficient though and I think any use-case that would need such a construction would be better of using a php page router. For fancy url's Jon Lin's solution would probably work better. It does however sort-of mimic what I had in mind.
I'll, however, put the code in here for demonstration:
#Parse all query key-value pairs to an environment variable with the q- prefix
RewriteCond %{QUERY_STRING} ^([^=]*)=([^&]*)(&(.*)|$)$
RewriteRule ^(.*)$ $1?%4 [E=q-%1:%2,N]
#If 'param1' existed in the query string...
RewriteCond %{ENV:q-param1} !^$
RewriteRule ^foo$ bar/%{ENV:q-param1} [END]
or even...
#Keep the original query string
RewriteCond %{ENV:qstring} ^$
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule .* - [E=qstring:#%1]
#parse the query parameters to environment variables
RewriteCond %{ENV:qstring} ^#([^=]*)=([^&]*)(&(.*)|$)$
RewriteRule ^(.*)$ - [E=q-%1:%2,E=qstring:#%4,N]
#See that the original query string is still intact
RewriteCond %{ENV:q-param1} !^$
RewriteRule ^foo$ bar/%{ENV:q-param1} [QSA]

Related

.htaccess remove GET completely

I have dozens of redirects from an old page e.g. index.php?mode=1,2,3,0 and I want to get rid of all GET Params because the new page is anyways just plain html.
RewriteCond %{REQUEST_URI} ^/index\.php$
RewriteCond %{QUERY_STRING} mode=17,0,0,0,0$
RewriteRule (.*) /big-mamas-house/ [R=301,L]
I thought removing (.*) would already do the trick but then the rule is not applied anymore according to:
http://htaccess.madewithlove.be/
Your rule can simplified to:
RewriteCond %{QUERY_STRING} ^mode=17,0,0,0,0$
RewriteRule ^index\.php$ /big-mamas-house/? [R=301,L,NC]
? in the end is needed to strip off any previous query string.

RewriteCond: 2 parameters for QUERY_STRING

I am dealing with an API that is accessing an URL on my website and adding
/?parameter1=value&parameter2=value to the url. I want my htaccess to handle this request and only keep the parameter's values. The API is also adding many other parameters in the query string but I just want to keep two of them.
The following does not work:
RewriteCond %{QUERY_STRING} ^parameter1=([^&]+)
RewriteCond %{QUERY_STRING} ^parameter2=([^&]+)
RewriteRule ^my-url/?$ controller.php?parameter1=%1&parameter2=%2
How can I do that correctly?
EDIT:
Here is an example.
The url is:
http://example.com/my-url/?parameter1=value1&stuff=1&stuff2=2&parameter2=value2
The htaccess should get the parameter1 & parameter2 values.
Try this and just grab the two parameters in your server side code. e.g. $_GET. If they are always in the query string, you can just check for parameter1 and then it will append the other parameters and you can get what you need.
RewriteCond %{QUERY_STRING} ^\bparameter1=
RewriteRule ^my-url/?$ controller.php [QSA,L]
Try the following:
RewriteEngine On
RewriteCond %{THE_REQUEST} ^(GET|POST)\ /my-url/\?parameter1=(.*)&stuff=(.*)&stuff2=(.*)&parameter2=(.*)\ HTTP
RewriteRule ^ /controller.php?parameter1=%2&parameter2=%5\? [R,L]
Mind it will only get the two parameters if there are always &stuff=1&stuff2=2 those two values in the url.
I've had to do a similar setup with key/value pairs in the GET which could come in any order depending on the client platform.
Based on useful pointers in this thread, this is what I came up with based on the question above:
#= 1. Catch parameter1, append querystring as "p1=". Rewrite to "/parameter1" below:
RewriteCond %{REQUEST_URI} ^/my-url/$
RewriteCond %{QUERY_STRING} ^parameter1=([^&]+)
RewriteRule (.*) /parameter1?%{QUERY_STRING}&p1=%1 [P,QSD]
#= 2. Catch parameter2, append querystring as "p2=". Rewrite to "/parameter2" below:
RewriteCond %{REQUEST_URI} ^/parameter1$
RewriteCond %{QUERY_STRING} ^parameter2=([^&]+)
RewriteRule (.*) /parameter2?%{QUERY_STRING}&p2=%1 [P,QSD]
#= 3. Now explicitly catch p1,p2 and feed to them to the back-end url:
RewriteCond %{REQUEST_URI} ^/parameter2$
RewriteCond %{QUERY_STRING} p1\=([^&]+)&p2\=([^&]+)$
RewriteRule (.*) controller.php?parameter1=%1&parameter2=%2 [P,L,QSD]
The above works fine for me but I do notice it a tiny bit slow to process, so if anyone has any criticism then I would be glad to hear it!

Htaccess query string

I am trying to make:
http://www.specialisedorthoticservices.co.uk/image.php?object_type=detailed&image_id=140&window=popup
become this:
http://www.specialisedorthoticservices.co.uk
The result of the query no longer exists and the re-direct doesn't seem to work see code below:
RewriteCond %{REQUEST_URI} ^/image\.php$
RewriteCond %{QUERY_STRING} ^object_type=detailed&image_id=140&window=popup$
RewriteRule ^(.*)$ http://www.specialisedorthoticservices.co.uk [R=301,L]
Remove the slash before image.php. In fact, why not just shorten it? To not append the query string you need a terminating question mark like so
RewriteEngine On
RewriteCond %{QUERY_STRING} ^object_type=detailed&image_id=140&window=popup$
RewriteRule ^image\.php$ /? [R=301,L]

PHP RewriteRule detect if url contain "string" and replace

This may be a basic question regarding RewriteRule but I just counldn't make it work.
What I want to do is detect urls like:
mydomain/myapp/id/some/random/url.html?param=somethingThatIdoUse
mydomain/myapp/id/other/randomabc/perrito.php?param=somethingThatIdoUse
...
The part that I need to discart is from the /id/[all this]?param=somethingIdoUse and use the param if is possible or send the complete url as param so I can regex to get the param.
And have a rule that detect that /id/ exist and redirect to something like:
mydomain/myapp/other/manageRequest.php?params=somethingThatIdoUse
(the params I could get the whole url and strip it as string is no problem)
As well the application have different modules like:
mydomain/myapp/moduleOne/index.php
mydomain/myapp/moduleTwo/index.php
This have to keep working the same.
As far I've tried some of them like:
RewriteEngine On
RewriteCond %{THE_REQUEST} ^GET /.*;.* HTTP/
RewriteCond %{QUERY_STRING} !^$
RewriteRule .* http://localhostdev/app/index.php %{REQUEST_URI}? [R=301,L]
RewriteEngine On
RewriteBase /spt/
RewriteCond %{REQUEST_FILENAME} !^id$ [NC]
RewriteRule ^(.*)$ index.php [R=301,L]
RewriteEngine On
RewriteCond %{REQUEST_URI} !/campaings/response\.php$
RewriteRule ^/something/(.*) /other/manageRequest.php? [L]
But nothing seamed to do kind of what I needed.
Thanks in advice
mydomain/myapp/id/some/random/url.html?param=somethingThatIdoUse
Here is an example using the above URL:
RewriteRule ^id/some/random/url.html/? /myapp/other/manageRequest.php [L,NC]
The query will be passed through unchanged to the substitution URL
well actually end up being really basic it worked with:
RewriteRule ^.*id.*$ handleRequest.php [NC,L]
I do get the params as they are sent!

Default Query String in .htaccess

Bit of an odd question, but I'd like to have a query string set on all of my URLs. If the parameter isn't set (or is empty), then I'd like to redirect to include a default.
For example:
example.com would need to requrect to example.com?param=a
example.com?param would also need to redirect to example.com?param=a
If the param is set and is part of a list of known values, then it should carry on as normal:
example.com?param=(a|b|c|d) would go to the respective page a,b,c or d
Some pages of the site use other parameters to sort and paginate, so the rules cannot assume that this is the only query string.
I've tried a couple of things, but kept getting stuck in a redirect loop. This is trying to set the default param:
RewriteCond %{QUERY_STRING} !(^|&)param=(a|b|c|d)($|&)
RewriteRule ^(.*)$ /index.php?rq=$1&param=a [L,QSA]
The main CMS rewrite rule is:
RewriteCond %{REQUEST_URI} !^\/*(index\.php|blog|admin\/assets|site\/assets|robots.txt|sitemap(|\-[0-9]+)\.xml|products.xml|favicon\.ico)
RewriteRule ^(.*)$ /index.php?rq=$1 [L,QSA]
Any help would be great!
RewriteCond %{QUERY_STRING} !(^|&)param=(a|b|c|d)($|&)
RewriteCond %{REQUEST_URI} !^\/*(index\.php|blog|admin\/assets|site\/assets|robots.txt|sitemap(|\-[0-9]+)\.xml|products.xml|favicon\.ico)
RewriteRule ^(.*)$ $1?%{QUERY_STRING}&param=a [L]
RewriteCond %{REQUEST_URI} !^\/*(index\.php|blog|admin\/assets|site\/assets|robots.txt|sitemap(|\-[0-9]+)\.xml|products.xml|favicon\.ico)
RewriteRule ^(.*)$ /index.php?rq=$1 [L,QSA]

Resources