htaccess rewriterule, [R,L=301] flags does not stop it. Why? - .htaccess

The beginning of .htaccess is
RewriteEngine On
#begin of rules for administration folder, redirect to https, if not https
RewriteCond %{REQUEST_URI} ^/administration
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R,L=301]
#end of rules for administration folder
#===no rules for /administration folder below this line===
#the rest part of .htaccess
Why does the rest part of .htaccess still performs for https://www.mydomain.com/administration/index.php ? How to stop the performing of the rest part of .htaccess file for urls that follow to administration folder? What's wrong in my code?
Thank you.

RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Add this line on top of your .htaccess file:
RewriteRule ^administration - [NC,L]

I had simmilar issue these days and I got a really interesting answer from the user DaveRandom in the PHP chat:
"Basically, mod_rewrite effectively runs in a loop (this isn't really true but effectively that's what it does) and the [L] flag is like a "continue" statement in PHP (it stops processing the rules below in the current iteration but it will then start processing the rules again from the top). So in your rules, the first iteration was matching the first rule, and then the second iteration skipped the first rule (it produced the same output as the input) and then matched the second rule."
Possible Solution: "if you are using apache 2.4 using [END] instead of [L] would be a fix".

It is because you have syntax error. .htaccess will ignore erroring lines
Change this:-
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R,L=301]
To this:-
RewriteRule .? https://%{HTTP_HOST}%{REQUEST_URI} [R=301]

Related

Converting NGINX rule to .htaccess

I'm trying to convert the following NGINX rule:
location ~ "^/calendrier/[0-9]{4}" {
rewrite ^/calendrier/(.*)$ /calendar/$1;
}
to .htaccess. I tried:
RewriteCond ^/calendrier/[0-9]{4} [NC]
RewriteRule ^/calendrier/(.*)$ /calendar/$1 [QSA,L]
but it isn't working.
Please help.
Thanks
You need to review the mod_rewrite documentation before attempting to convert rules from other platforms. Reason being: it is essential that you understand exactly how mod_rewrite should be used so that conversions are painless.
The problem with your conversion is that the RewriteCond is not checking that pattern against anything. Essentially, you've just done guess-work to see if it does what you want.
You only need to place the following in your /.htaccess file:
RewriteEngine on
RewriteRule ^calendier/([0-9]{4})/?$ /calendar/$1 [L]
The first part of the rule checks for calendier/<some_number> with an optional trailing slash (If you do not want the slash, you can remove /?).
This is the rewrite I used to get the job done.
RewriteCond %{REQUEST_URI} ^/calendrier/ [NC]
RewriteRule ^calendrier/(.*)$ /calendar/$1 [NC,L]

.htaccess file ignored on Ubuntu server

I have recently moved to a new server for my website, and i activated mod_rewrite with success, but some files still not working !
Like this one:
RewriteRule ^activate\/(.*)\/(.*)$ activate.php?Email=$1&hash=$2
I have made all necessary changes on my VPS (Ubuntu) !
Any idea ?
Like this lines work well:
RewriteRule ^search\/(.*)\/([a-zA-Z0-9_-]+)$ search.php?view=$1&p=$2
RewriteRule ^search$ searchResults.php
RewriteRule ^term$ term.php
RewriteRule ^faq$ faq.php
# Non-working line...
RewriteRule ^activate\/(.*)\/(.*)$ activate.php?Email=$1&hash=$2
Note that mod_rewrite are enabled and all other lines work well only this one !
First thing, you must define a RewriteBase because of your two rules (first and last) that create both virtual directories.
Then, you should disable MultiViews option to make term or faq rule work without problem.
Finally, you can rewrite your patterns in a more generic way (or at least in a better way, more precise). Also, don't forget L flag ([L]) after each rule, otherwise mod_rewrite continues to evaluate next rules.
You can replace your current code in your htaccess by this one (assuming your htaccess is in root folder)
Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteRule ^search/([^/]+)/([^/]+)$ search.php?view=$1&p=$2 [L]
RewriteRule ^search$ searchResults.php [L]
RewriteRule ^term$ term.php [L]
RewriteRule ^faq$ faq.php [L]
RewriteRule ^activate/([^/]+)/([^/]+)$ activate.php?Email=$1&hash=$2 [L]

url rewrite how to send everything else to index.php condition

there,
This sould be a simple task for anyone who knows, but I am new to Apache rewrites, so please bear with me.
I wrote 2 rewrite conditions and they work. I need to write a third - so that everything else would go to index.php file. The problem is - if I add the third rule, it is always applied despite first 2.
RewriteEngine On
RewriteRule ^new/?$ new.php [NC,L]
RewriteRule ^thanks(.*)$ thankyou.php [NC,L]
RewriteRule ^(.*)$ index.php
Thanks for help.
I believe the answer lies in the following paragraph about the L flag used with the RewriteRule directive:
If you are using RewriteRule in either .htaccess files or in
sections, it is important to have some understanding of
how the rules are processed. The simplified form of this is that once
the rules have been processed, the rewritten request is handed back to
the URL parsing engine to do what it may with it. It is possible that
as the rewritten request is handled, the .htaccess file or
section may be encountered again, and thus the ruleset may be run
again from the start. Most commonly this will happen if one of the
rules causes a redirect - either internal or external - causing the
request process to start over.
I think what happens is that after the rewrite is executed, somehow control is given back to the URL parsing engine and the rules are run again.
You can prevent this behaviour by adding a few rewrite conditions to the last rule:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule new/?$ new.php [NC,L]
RewriteRule thanks(.*)$ thankyou.php [NC,L]
# Only rewrite to index.php if the current request is not for an existing file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
</IfModule>

htacces redirect and mask

How would I redirect from the root folder to a sub folder and then mask that folder?
So instead of http://root.com/sub_folder
It would be just http://root.com
I have tried:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^root\.com$
RewriteRule (.*) http://root.com/$1 [R=301,L]
RewriteRule ^$ /sub [L]
However, that does not work. Any help will be welcome.
To clarify what I think you're looking for:
You want users who enter http://root.com with no trailing path to be rewritten silently to http://root.com/sub.
If a user directly enters http://root.com/sub, however, you want them to be redirected to http://root.com.
Any other path within root.com should be left alone.
The following two rules accomplish this. If you have more than one domain and only want this to apply to one domain, add your original RewriteCond in front of each RewriteRule.
RewriteRule ^sub/?$ http://root.com/ [R=301,L]
RewriteRule ^$ /sub [END]
First rule redirects /sub with or without trailing slash to root.com. Second rule rewrites base domain to /sub.
EDIT: Per Jon Lin's comment, below, the [L] flag only stops the current round of processing and internal rewrites are sent through the rules once more (I always forge that part). So, you can terminate the second line with [END] instead, which stops all rewrite processing. The catch is that [END] is only available in Apache 2.4 or higher, so if you're on an older version something trickier will need to be done.

Remove trailing slash with mod_rewrite

I've tried every single example I could find, they all produce an internal server error. I have these rules set up (this works, no error):
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}/index.php !-f
RewriteRule ^((/?[^/]+)+)/?$ ?q=$1 [L]
So if it's not an existing file or an existing directory with an index.php we redirect. For instance, http://domain.com/foo/bar becomes http://domain.com/?q=foo/bar
Thing is, I want the trailing slash stripped. So take off the /? at the end of the rule. How do I make it so that http://domain.com/foo/bar/ becomes http://domain.com/foo/bar with a visible redirect first (fixing the client's URL), and only then the real, silent redirection to ?q=?
Everywhere I look I see this:
RewriteRule (.*)/$ $1 [R,L]
But it gives me a 500 error if I insert it before my rule.
If foo/bar exists as a real directory, then the server will be redirecting the client to foo/bar/ (with the trailing slash). It has to do that in order for relative URLs to work correctly on the client. If you put in a rule to rewrite that back to foo/bar with a redirect then there will be a loop. An easy way to test if that's happening is to specify a path that doesn't exist at all (I assume from your index.php detection that the directory tree actually exists). The nonexistent path won't trigger the built-in redirect.
If I setup a similar set of rules to yours (plus the suggested slash-removal rule) I can see the difference between a directory that exists and one that doesn't. The ones that don't work as expected, the ones that do cause Firefox to say This page isn't redirecting properly. IE8 says something similar. Perhaps the Apache setup you're using can detect it and turns it into the 500 error?
It looks like the simpler rewrite rule you mention at the end of your question should work. The problem is, the 500 error isn't really helpful in figuring out why it's not working. One way I've found useful in helping debug mod_rewrite errors is to enable it's logging. Add the following to your httpd.conf:
RewriteLog "/usr/local/var/apache/logs/rewrite.log"
RewriteLogLevel 3
Then try again, and look in the log to see what's going on. Once you're done, you can disable the log be setting the rewriteloglevel 0. See the mod_rewrite docs for details.
Try this rule in front of your current rule:
RewriteRule (.*)/$ /$1 [R,L]
Try these rules:
#prevent mod_dir from adding slash
DirectorySlash Off
#redirect /folder/ to /folder
RewriteCond %{THE_REQUEST} ^GET\s\S+/(\?\S+)?\s [NC]
RewriteRule ^(.*)/$ /$1 [R=301,L,QSA]
#internal redirect for directories
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !/$
RewriteRule ^(.*)$ /$1/ [L]

Resources