mod_rewrite deny access if parameter equals something - .htaccess

I have urls like
mydomain.com?act=somethingbad
mydomain.com?act=somethingworse
and
mydomain.com?act=somethinggood
mydomain.com?act=somethingbetter
I need to make bad actions forbidden.
Tried something like:
RewriteCond %{QUERY_STRING} act=(.*)
RewriteCond %{QUERY_STRING} act=[^(somethinggood)]
RewriteRule ^(.*) - [F]
Because I have more bad actions than good I want to exclude de good actions from this rule.
But the above example doesn't work.

Use these rules:
RewriteCond %{QUERY_STRING} (^|&)act=(.*)
RewriteCond %{QUERY_STRING} !(^|&)act=(somethinggood|somethingbetter)(&|$)
RewriteRule ^(.*) - [F]
Parameter act can be any where (e.g. http://example.com/?act=somethinggood and http://example.com/?mode=happy&act=somethinggood and http://example.com/?mode=happy&act=somethinggood&extra=yes will be OK)
If you will have empty value for act parameter, it will be rejected (e.g. http://example.com/?act= is treated as BAD parameter)
Based on URL examples you have provided, this rule will be applied for ALL URLs that have act parameter in query string.

Related

RewriteCond for query parameters in .htaccess files

I have to write some Rewrite Rules and I need to make a check based on my query parameters.
The public url is something like this abc.com/lmn/xyz.json and there is an optional parameter optparam.
This is what I want to achieve:
If optparam is present and not equal to false, the conditions have to fail and carry on with other rules.
After reading through few blogs and posts, I have a very faint idea about these rules. So tried this:
RewriteCond %{QUERY_STRING} !^optparam $ [NC,OR]
RewriteCond %{QUERY_STRING} ^optparam=false$ [NC]
RewriteRule ^lmn/xyz.json$ xyz.json
But the RewriteRule is applied even when I send the param value to be true.
Please tell me what I am missing here.
Thanks in advance!
Examples:
abc.com/lmn/xyz.json ==> Rule should fire
abc.com/lmn/xyz.json?optparam ==> Rule should not fire
abc.com/lmn/xyz.json?optparam=false ==> Rule should fire
abc.com/lmn/xyz.json?optPARAM=hfjsgzjrg ==> Rule should not fire
abc.com/lmn/xyz.json?optParam=FALSE ==> Rule should fire
Change your rule to this:
RewriteCond %{QUERY_STRING} ^(optparam=false)?$ [NC]
RewriteRule ^lmn/xyz\.json$ xyz.json [L,NC]
Well, I think an additional check of optparam not present at all is required. Tried this:
RewriteCond %{QUERY_STRING} (^$|!^optparam$|^optparam=false$) [NC]
RewriteRule ^lmn/xyz\.json$ xyz.json [L,NC]
This seems to work for me. But is there any way to further shorten this condition? I believe I am not using regex to its full potential here.

mod_rewrite and redirect causing loop

I have problem when I try to redirect and rewrite together.
I have site example.com/show_table.php?table=12 (max 99 tables). I wanted nice links, so I got this .htacces rw rule:
RewriteRule ^table/([0-9]{1,2})$ show_table.php?table=$1 [L,NC]
Now are links something like example.com/table/12 - it's definitely OK. But I want all old links redirect to new format. So I use Redirect 301, I added to .htaccess this code:
RewriteCond %{REQUEST_URI} show_table.php
RewriteCond %{QUERY_STRING} ^table=([0-9]{1,2})$
RewriteRule ^show_table\.php$ http://example.com/table/%1? [L,R=301,NC]
But when I visit example.com/show_table.php?table=12, I receive just redir-loop. I don't understant - the first is rewrite, the second is redirection, there ain't no two redirections. Do You see any error?
Thanks!
Instead of checking REQUEST_URI in the condition, you need to be checking in THE_REQUEST (which contains the full original HTTP request, like GET /show_table.php HTTP/1.1). When Apache performs the rewrite, it changes REQUEST_URI, so to the rewritten value, and that sends you into a loop.
# Match show_table.php in the input request
RewriteCond %{THE_REQUEST} /show_table\.php
RewriteCond %{QUERY_STRING} ^table=([0-9]{1,2})$
# Do a full redirection to the new URL
RewriteRule ^show_table\.php$ http://example.com/table/%1? [L,R=301,NC]
# Then apply the internal rewrite as you already have working
RewriteRule ^table/([0-9]{1,2})$ show_table.php?table=$1 [L,NC]
You could get more specific in the %{THE_REQUEST} condition, but it should be sufficient and not harmful to use show_table\.php as the expression.
You'll want to read over the notes on THE_REQUEST over at Apache's RewriteCond documentation.
Note: Technically, you can capture the query string in the same RewriteCond and reduce it to just one condition. This is a little shorter:
# THE_REQUEST will include the query string so you can get it here.
RewriteCond %{THE_REQUEST} /show_table\.php\?table=([0-9]{1,2})
RewriteRule ^show_table\.php$ http://example.com/table/%1? [L,R=301,NC]

Redirect olddomain querystring layout to newdomain and new querystring layout?

OK, say my blog site myurl.org as many links to a separate domain:
old.myurl.org?oldvar=foo
Only old.myurl.org no longer exists and has been replaced by new.myurl.org.
If the query string vars were the same on new.myurl.org, I believe I could rewrite from .htaccess using:
RewirteCond %{http_host} ^old.myurl.org$ [NC]
RewriteRule ^(.*)$ new.myurl.org [L,R=301,QSA]
The only problem is that I also need to change the query string var from oldvar to newvar and preserve it's data (foo).
There are plenty of examples of how to rewrite query string vars in different ways, but I can't seem to find an example of this scenario.
I need to rewrite:
old.myurl.org?oldvar=foo
To:
new.myurl.org?newvar=foo
Edit
Furthermore, I have several potential query string key values to account for, but not all will always be present.
So I may need:
old.myurl.org?oldvar=foo&oldvar2=bar --> new.myurl.org?newvar=foo&newvar2=bar
or
old.myurl.org?oldvar2=bar --> new.myurl.org?newvar2=bar
This may not even be possible, but in one case I need to strip off part of the query string value. So ?oldvar=foo{term} might need to become ?newvar=foo
Thanks again!
First condition match the domain, second condition match the query string and the rule will match your domain root:
RewriteCond %{HTTP_HOST} ^old\.myurl\.org$ [NC]
RewriteCond %{QUERY_STRING} ^oldvar=(\w+)$
RewriteRule ^$ http://new.myurl.org/?newvar=%1 [R=301,L]
You can place more than one query string as well:
RewriteCond %{HTTP_HOST} ^old\.myurl\.org$ [NC]
RewriteCond %{QUERY_STRING} ^oldvar=(\w+)$ [OR]
RewriteCond %{QUERY_STRING} ^oldvar=(\w+)&oldvar2=(\w+)$
RewriteRule ^$ http://new.myurl.org/?newvar=%1&newvar2=%2 [R=301,L]
RewriteCond %{HTTP_HOST} ^old\.myurl\.org$ [NC]
RewriteCond %{QUERY_STRING} ^oldvar2=(\w+)$
RewriteRule ^$ http://new.myurl.org/?newvar2=%1 [R=301,L]
To use a path like x/y/z as you have mentioned on the comment you change the RewriteRule for example the rule we are currently using, will only redirect from yourdomain.com/?... which is:
RewriteRule ^$ http://new.myurl.org/?newvar2=%1 [R=301,L]
If you want to catch a different path you would do this:
RewriteRule ^x/?$ http://new.myurl.org/?newvar2=%1 [R=301,L]
The above would catch yourdomain.com/x?... and yourdomain.com/x/?...
You can have more than one path as well and use a OR condition like this:
RewriteRule ^(x|x/y|x/y/z)/?$ http://new.myurl.org/?newvar2=%1 [R=301,L]
The above means we want to match x/?... OR x?... OR x/y?... and x/y/?... OR x/y/z?... OR x/y/z/?...
By encapsulating it on the parenthesis and using the | as separator and OR.
The ^ and $ means match from begin to end, so when it contains nothing means match nothing which means root folder domain.com/, when there is content it will match the content for instance domain.com/x or whatever you place into it.

How do I redirect a url with parameters

How do I redirect a url with parameters
I will like to write this url:
http://mydomain.com/dk/silkeborg?latitude=56.1631229&longitude=9.536976500000037&zoom=14
and redirect it to
http://mydomain.com/index.php?country=dk&city=silkeborg&latitude=56.1631229&longitude=9.536976500000037&zoom=14
To day I use the below rule, that don't take any parameters
RewriteRule (dk|de)/(.*) index.php?country=$1&city=$2 [NC]
Please help me
You do need to use [QSA] because you're rewriting the query (it's enabled by default unless you rewrite the query). Here we're capturing the country code and passing it as a var. Then QSA is catching the rest of the variables and adding them to the query string.
RewriteCond %{REQUEST_URI} ^/(dk|de)/ [NC]
RewriteRule .* index.php?country=%1 [QSA,L]
To use your existing rule, you would append [QSA]
RewriteRule (dk|de)/(.*) index.php?country=$1&city=$2 [QSA,NC,L]
When the page loads you can access the country via $_GET['country'] and city via $_GET['city'].

mod_rewrite regex (too many redirects)

I am using mod_rewrite, to convert subdomains into directory urls. (solution from here). When I explicity write a rule for one subdomain, it works perfectly:
RewriteCond %{HTTP_HOST} ^[www\.]*sub-domain-name.domain-name.com [NC]
RewriteCond %{REQUEST_URI} !^/sub-domain-directory/.*
RewriteRule ^(.*) /sub-domain-directory/$1 [L]
However, if I try to match all subdomains, it results in 500 internal error (log says too many redirects). The code is:
RewriteCond %{HTTP_HOST} ^[www\.]*([a-z0-9-]+).domain-name.com [NC]
RewriteCond %{REQUEST_URI} !^/%1/.*
RewriteRule ^(.*) /%1/$1 [L]
Can anyone suggest what went wrong and how to fix it?
Your second RewriteCond will never return false, because you can't use backreferences within your test clauses (they're compiled during parsing, making this impossible since no variable expansion will take place). You're actually testing for paths beginning with the literal text /%1/, which isn't what you wanted. Given that you're operating in a per-directory context, the rule set will end up being applied again, resulting in a transformation like the following:
path -> sub/path
sub/path -> sub/sub/path
sub/sub/path -> sub/sub/sub/path
...
This goes on for about ten iterations before the server gets upset and throws a 500 error. There are a few different ways to fix this, but I'm going to chose one that most closely resembles the approach you were trying to take. I'd also modify that first RewriteCond, since the regular expression is a bit flawed:
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$ [NC]
RewriteCond %1 !=www
RewriteCond %1#%{REQUEST_URI} !^([^#]+)#/\1/
RewriteRule .* /%1/$0 [L]
First, it checks the HTTP_HOST value and captures the subdomain, whatever it might be. Then, assuming you don't want this transformation to take place in the case of www, it makes sure that the capture does not match that. After that, it uses the regular expression's own internal backreferences to see if the REQUEST_URI begins with the subdomain value. If it doesn't, it prepends the subdomain as a directory, like you have now.
The potential problem with this approach is that it won't work correctly if you access a path beginning with the same name as the subdomain the request is sent to, like sub.example.com/sub/. An alternative is to check the REDIRECT_STATUS environment variable to see if an internal redirect has already been performed (that is, this prepending step has already occurred):
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$ [NC]
RewriteCond %1 !=www
RewriteCond %{ENV:REDIRECT_STATUS} =""
RewriteRule .* /%1/$0 [L]

Resources