Understanding .htaccess rewrite rule - .htaccess

I stumbled upon this .htaccess file and am trying to figure out what it does.
RewriteEngine On
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{REQUEST_URI} !index\.php$
RewriteCond %{REQUEST_URI} !upload\.php$
RewriteRule ^ - [L,H=default-handler]

RewriteEngine On
Line above says , you activate mod_rewrite
RewriteCond %{REQUEST_URI} !/$
Line above is a condition to be applied with URI , URI is a part of path after host not including query string http://httpd.apache.org/docs/current/mod/mod_rewrite.html , for example http://example.com/whatever/index.php , /whatever/index.php is the URI part in this case , then there is !/$ with means ! not end $ with / so this condition will match any URI that not ends with /
RewriteCond %{REQUEST_URI} !index\.php$
RewriteCond %{REQUEST_URI} !upload\.php$
Two line above also are conditions to don't match URIs that end with either index.php or upload.php
RewriteRule ^ - [L,H=default-handler]
Above line illustrates the rule that should applied according to those conditions and it includes Pattern , substitution and flags , you can read more here https://httpd.apache.org/docs/2.4/rewrite/intro.html and herein means any request passes conditions above will be handled by default handler , So the Pattern is ^ which is regular expression https://httpd.apache.org/docs/2.4/rewrite/intro.html means matches the beginning of the string and substitution is - which means do nothing then the flags [L,H=default-handler] , L means stop processing the rule set , H means forces the resulting request to be handled with the specified handler and it is default handler in your case .
see this about flags https://httpd.apache.org/docs/2.4/rewrite/flags.html and this to understand handler https://httpd.apache.org/docs/2.4/handler.html

Related

How to rewrite a directory to a cookie value in .htaccess?

$val = substr(str_shuffle(str_repeat("abcdefghijklmnopqrstuvwxyz0123456789", 12)), 0, 12);
setcookie('sub' , $val , time() + (86400) , '/');
example.com/folder/file.php should be rewritten to the value of $_COOKIE['sub'] e.g. example.com/6df1fcb7aba6/file.php
How can I do that?
I tried this:
RewriteCond %{HTTP_COOKIE} !^.*sub.*$ [NC]
RewriteRule %{HTTP_COOKIE} !^.*sub.*$/(.*) folder/$1
, but doesn't work
You can do something like the following in the root .htaccess file using mod_rewrite:
RewriteEngine On
RewriteCond %{HTTP_COOKIE} (?:^|;|\s)sub=([a-z0-9]{12})(?:$|;)
RewriteRule ^folder/(file\.php)$ %1/$1 [L]
The above states:
Given a request for /folder/file.php
And the cookie sub exists with a 12 char alphanumeric (lowercase) value.
Rewrite the request to /<sub-cookie-value>/file.php
The %1 backreference contains the value of the sub cookie, providing it meets the criteria of being a 12 char alphanumeric (lowercase) value.
The $1 backreference simply contains file.php as captured from the RewriteRule pattern.
RewriteCond %{HTTP_COOKIE} !^.*sub.*$ [NC]
RewriteRule %{HTTP_COOKIE} !^.*sub.*$/(.*) folder/$1
The RewriteRule pattern (first argument) is a regex that matches against the requested URL-path, so %{HTTP_COOKIE} (seen as a literal string) will never match, so the rule does nothing. However, the syntax of the 3rd argument (flags) is entirely invalid so is likely to result in a 500 Internal Server Error ("bad flags delimiter").
The RewriteCond directive is checking that the string sub does not occur anywhere in the Cookie HTTP request header, which is not what you want to do. You need to check that sub is present and extract the value.

add string at the end of URL using htaccess which has query string also

I want to change
domain.com/division1/index.php?members/maxmusterman.5
to
domain.com/division1/index.php?members/maxmusterman.5/#div
That is if the URL contains index.php?members, then I add /#div at the end of url. I tried this
RewriteEngine On
RewriteCond %{REQUEST_URI} index.php?
RewriteRule (.*) /%1/%{QUERY_STRING}&123 [L,QSA,R=301]
but it returns
domain.com/members/maxmusterman.5&123?members/maxmusterman.5
Note here that &123 is attached after URI before starting parameters. I researched htaccess QSA flag but I could not find a way to add a custom string at the end of the query string. How can I do that. Here I have used &123 for test purpose, actual requirement is adding /#div
To redirect
domain.com/division1/index.php?members/maxmusterman.5
to
domain.com/division1/index.php?members/maxmusterman.5/#div
.
You can use something like the following :
RewriteEngine on
RewriteCond %{QUERY_STRING} !loop=no
RewriteRule ^division1/index\.php$ %{REQUEST_URI}?%{QUERY_STRING}&loop=no#div [L,R,NE]
I added an additional perameter loop=no to the destination url to prevent infinite loop error .You can't avoid this as both your old url and the new url are identical and can cause redirect loop if you remove the RewriteCond and Query perameter.
NE (no escape ) flag is important whenever you are redirecting to a fragment otherwise mod-rewrite converts the # to its hex %23 .
solution #2
RewriteEngine on
RewriteCond %{THE_REQUEST} !.*loop=no [NC]
RewriteCond %{THE_REQUEST} /division1/index\.php\?(.+)\s [NC]
RewriteRule ^ /division1/index.php?%1&loop=no#div [NE,L,R]
Clear your browser cache before testing these redirects.

Rewrite rules gives inifinite loop (error 500) despite [L] option

I have to types of urls. The first one contains number and the second does not, e.g.:
/forms/my-forms/form/123/edit
/forms/my-forms/
I want to take out all numbers from path (if they have no letters before/after the / sings so e.g. 123 but not a123) to $_GET variable and the rest of the path to another $_GET so I will have something like that after rewriting:
index.php?path=forms/my-forms/form/edit&id=123
index.php?path=forms/my-forms/
I've created the .htaccess for this:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond $1 !^(index\.php|robots\.txt)
RewriteRule ^(.*)/([0-9]+)(.*)?$ ./index.php?path=$1$3&id=$2 [L]
RewriteRule ^(.*)$ ./index.php?path=$1 [L]
But it gives me infinitive loop (500 Interla Server Error), despite using [L] for both rules.
When I remove one of the rules, the other works fine (but of course I only have processing of first or second type of urls).
L flag doesn't do what you think it does. L just exists the current Rewrite Cycle and sends the uri for next fase of processing. You are getting rewrite loop error because of your last rule
RewriteRule ^(.*)$ ./index.php?url=$1 [L]
This rewrites everything to /index.php , for your example
in first iteration
http://example.com/foobar gets rewritten to /index.php?url=foobar and then , On the second rewrite iteration /index.php?url=foobar gets rewritten to itself /index.php?url= and thus apache return a 500 Error status to client.
To fix the loop error, you need to tell mod-rewrite to exit the rule processing in first iteration, You can Replace L with END if you are on apache 2.4 , if you are on lower version of apache you can use the following condition above the rule that is causing internal loops
RewriteCond %{ENV_REDIRECT_STATUS} !200
Try with below rule, I didn't tried for now but .* is the one causing problem It matches everything in url and after that most of the rule cease to work other than with .*.
RewriteRule ^(.+?)/([0-9]+)(.+?)?$ ./index.php?path=$1$3&id=$2 [L]
RewriteRule ^(.+?)$ ./index.php?path=$1 [L]

Stop hotlinking using htaccess and non-specific domain code

I need to write an anti-hotlink command for my .htaccess file but it can not be specific to any domain name in particular. Here's what I found on another sites so far but I'm not sure exactly why it doesn't work, can anyone spot the problem?
# Stop hotlinking.
#------------------------------
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} ^https?://([^/]+)/ [NC]
# Note the # is just used as a boundary. It could be any character that isn't used in domain-names.
RewriteCond %1#%{HTTP_HOST} !^(.+)#\1$
RewriteRule \.(bmp|gif|jpe?g|png|swf)$ - [F,L,NC]
Try this.
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} ^https?://(www\.)?([^/]+)/.*$ [NC]
RewriteCond %2#%{HTTP_HOST} !^(.+)#(www\.)?\1$ [NC]
RewriteRule \.(bmp|gif|jpe?g|png|swf)$ - [F,L,NC]
Would even work when only one of the referrer or target url has a leading www.
EDIT : (how does this % thing work?)
%n references the n(th) bracket's matched content from the last matched rewrite condition.
So, in this case
%1 = either www. OR "" blank (because it's optional; used ()? to do that)
%2 = yourdomain.com (without www always)
So, now the rewrite condition actually tries to match
yourdomain.com#stealer.com OR yourdomain.com#www.stealer.com
with ^(.+)#(www\.)?\1$ which means (.+)# anything and everything before # followed by www. (but again optional); followed by \1 the first bracket's matched content (within this regex; not the rewrite condition) i.e. the exact same thing before #.
So, stealer.com would fail the regex while yourdomain.com would pass. But, since we've negated the rule with a !; stealer.com passes the condition and hence the hot-link stopper rule is applied.

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