Combine Rewrite conditions in htaccess - .htaccess

I have many rewrite rules and conditions in my .htaccess as follows
RewriteCond %{QUERY_STRING} "limit"
RewriteRule scripts/api.php - [E=Cache-Control:max-age=3600]
RewriteCond %{QUERY_STRING} "limit"
RewriteRule scripts/api_1.php - [E=Cache-Control:max-age=3600]
RewriteCond %{QUERY_STRING} "limit"
RewriteRule scripts/api_2.php - [E=Cache-Control:max-age=3600]
RewriteCond %{QUERY_STRING} "limit"
RewriteRule scripts/api_3.php - [E=Cache-Control:max-age=3600]
RewriteCond %{QUERY_STRING} "limit"
RewriteRule scripts/api_4.php - [E=Cache-Control:max-age=3600]
The above conditions cache all urls contains "limit" word in the url of scripts/api.php followed by query string like '&' in urls. I need to add more apis like these, So is there a way to combine all these conditions and cache all urls contains scripts/api
Like
RewriteCond %{QUERY_STRING} "limit"
RewriteRule scripts/api* - [E=Cache-Control:max-age=3600]
I dont thik above condtion is correct one, can anyone suggest me the right way.

A rewrite rule accepts a regular expression as the first parameter, not a wildcard string pattern.
This probably is what you are looking for instead:
RewriteEngine on
RewriteCond %{QUERY_STRING} limit
RewriteRule ^/?scripts/api(_\d+)?\.php$ - [E=Cache-Control:max-age=3600]
It probably also would make sense to use a more precise pattern in the condition... For example to prevent other HTTP GET arguments to interfere in an unexpected manner, things like for example ...&otherArg=mylimit&... which probably is not what you want to accept as limit...

Related

How do I create dynamic friendly urls for a query string?

So currently I have URLs that looks like this:
http://localhost/?v=register
http://localhost/?v=profile&u=thatgerhard
I want the above to look like this:
http://localhost/register/ (without trailing /)
http://localhost/profile/thatgerhard/ (without trailing /)
I spent a ton of time trying to get this to work even though it seems like it should be a simple fix.
This is what I have atm:
RewriteBase /
RewriteEngine On
RewriteRule ^((.)*)$ /?v=$1&p=$
I would ideally like this to be dynamic so that if you do ?v=foo it will automatically do /foo/ without adding "foo" to the htaccess file.
Any help or direction will be greatly appreciated. :)
You should use RewriteCond Directive and RewriteCond backreferences. The %1 backreference matches the query string parameter v, the %2 backreference matches the query string parameter u. The RewriteRule redirects the request permanently and discard the query string entirely.
RewriteCond %{QUERY_STRING} ^v=([^&]*)$ [NC]
RewriteRule ^/?$ /%1/? [R=301,L]
RewriteCond %{QUERY_STRING} ^v=([^&]*)&u=([^&]*)$ [NC]
RewriteRule ^/?$ /%1/%2/? [R=301,L]

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!

Reference capture groups of multiple RewriteCond in RewriteRule

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]

optional parameter in url rewriting

I'm using apache and .htacess to rewrite my urls.
I would like to have an optional parameter "mess" in my ad.php page. I wrote :
RewriteRule ^ad-([A-Za-z0-9-]+)/?$ ad.php?id=$1 [NC,L]
RewriteRule ^ad-([A-Za-z0-9-]+)-([A-Za-z0-9-]+)/?$ ad.php?id=$1&mess=$2 [NC,L]
But it seems that only the first rule is considered. ad-100 and ad-100-1 should give different things but they don't. When I remove The first Rule, ad-100 is not working anymore (obviously) and ad-100-1 is now working because it's taking the second rule.
Do you know how I can have optional parameters ? Should I combine the two rule in one ?
This should work:
RewriteCond %{REQUEST_URI} !ad\.php [NC]
RewriteRule ^ad-([^-]+)/?$ ad.php?id=$1 [NC,L]
RewriteCond %{REQUEST_URI} !ad\.php [NC]
RewriteRule ^ad-([^-]+)-([^/]+)/? ad.php?id=$1&mess=$2 [NC,L]
Optionally, you could use one rule for both parameters if there is no problem having mess value empty when there is only one parameter. Like this:
RewriteCond %{REQUEST_URI} !ad\.php [NC]
RewriteRule ^ad-([^-]+)-?([^/]+)?/? ad.php?id=$1&mess=$2 [NC,L]

QUERY_STRING in .htaccess While redirecting

How can I allow visitors to use this link (www.example.com/news?id=34) in order to see (www.example.com/index.php?page=news&id=34)
Right now I am hiding the extensions of my PHP files in order to make the links look nice. When visitors go to (www.example.com/news) they can see the page (www.example.com/index.php?page=news). However, when they go to (www.example.com/news?id=12) they get a 404 error.
At this point, PHP does not recognize the id parameter. Here is what I currently have in my .htaccess file
Options +FollowSymlinks
RewriteEngine on
# catch request with no querystring like /Home
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^([^/]+)$ /index.php?page=$1 [L]
# make other requests with a non-empty query string go to /index.php?id=XXXXX
RewriteCond %{QUERY_STRING} ^.*$
RewriteRule ^$ /index.php?id=$1 [QSA,L]
Your second test pattern (^$) only matches the case where the user doesn't put any path information in, but does include a query string (e.g. www.example.com/?id=12). Also note that the backreference $1 has no value in that rule either.
The simplest solution is to just combine the two rules, since you can use the QSA flag to do the work of appending the id=# part for you:
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)$ /index.php?page=$1 [QSA,L]
The condition of your first rule fails as the query is not empty. Try it without that condition but with the following condition instead:
RewriteCond $1 !=index.php
RewriteRule ^([^/]+)$ /index.php?page=$1 [L]

Resources