.htaccess force to HTTPS in a folder - php

I am trying to redirect a forum index to use HTTPS for everything, but .htaccess is pretty new to me and i am learning so anyone could give a hand i would appreciate it :)
So i have the forum in a subdirectory called SMF. Currently everything is going to www.website.net/smf/index.php
But i wanted to redirect everything to HTTPS, while keeping the /smf/index.php structure.
Here is the current .htaccess i have in my main html_public:
# .htaccess main domain to subdirectory redirect
# Do not change this line.
RewriteEngine on
# Change example.com to be your main domain.
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
# Change 'subdirectory' to be the directory you will use for your main domain.
RewriteCond %{REQUEST_URI} !^/subdirectory/
# Don't change the following two lines.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Change 'subdirectory' to be the directory you will use for your main domain.
RewriteRule ^(.*)$ /subdirectory/$1
# Change example.com to be your main domain again.
# Change 'subdirectory' to be the directory you will use for your main domain
# followed by / then the main file for your site, index.php, index.html, etc.
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteRule ^(/)?$ subdirectory/index.php [L]
When i change ANYTHING, everything goes bananas. Everything in the forum is in subdirectory folder, including the index.php and so on. (please note i changed the website url to example.com and the subdirectory, to subdirectory only in copy paste code)
I am going bananas trying to make the website show https, but whenever i try something it doesnt work and gives me https://www.website.com//smf/index.php and i cant remove the // :(
Is there anyway i can clean the code and make it more simple and easier to understand?
Thanks!

I have had many nights struggling around the .htaccess file... But heres the deal, this file actually has nothing to do with php, but is actually associated with Apache. This is a separate program from PHP (which is its self a programing language and compiler). And not to get off on to much of a tangent, but this means you can run php in a terminal with out a browser. Any hoot, because Apache isn't programmed in PHP, and is solely designed to handle HTTP(s) server requests some of the code to make it work may be operating system dependent. This was the cause of a lot of struggle when running locally and trying to deploy to my remote server. This is all just from my experience, so if someone knows more please feel free to share.
This is what I use now to send to https.
# Remove www.
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
But I have used these variants before too.
#Turn on https ( Cent OS )
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Turn on https ( Mac OS )
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
I recommend for portability to make this feature yourself in php directly.
You can detect https using something like this below, which will set a global constant Boolean named 'HTTPS'
\define('HTTPS', ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? false) === 'https' || (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
This is php 7 code
Then you'd just redirect how you see fit if it false.

Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
## hide .php extension
# To externally redirect /dir/foo.php to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
RewriteRule ^ %1 [R=307,L,NC]
## To internally redirect /dir/foo to /dir/foo.php
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^ %{REQUEST_FILENAME}.php [L]
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^ %{REQUEST_FILENAME}.html [L]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.example.com/$1 [R,L]
#ErrorDocument 404 /404.php
#ErrorDocument 403 /403.php
Options -Indexes

Related

How to avoid the redirection to index.php when trying to access non www urls

I have a Laravel website in production and here is my problem explained with 4 simple url tests:
Access: https://www.my-website.kr/
Result: https://www.my-website.kr/ (all good)
Access: https://my-website.kr/ (home page again but without www
Result: https://www.my-website.kr/ (all good, redirects my non www
urls to www)
Access: https://www.my-website.kr/subpage
Result: https://www.my-website.kr/subpage (all good)
Access: https://my-website.kr/subpage
Result: https://www.my-website.kr/index.php (not good, I don't want this index.php)
This last test it the one I cannot fix and it is quite annoying. When I access a subpage without www; it's okay if the only solution is to get a redirection to the home page again but at least without the index.php this is terrible for the SEO.
I know these questions about htaccess have been answered many times but I am loosing hope... Even the technical support of my dedicated server couldn't answer me properly.
I have two htaccess files at the moment; one located directly at the root of my public_html/ with the following content:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} ^domain\.kr [NC]
RewriteRule ^(.*)$ https://www.domain.co.kr/$1 [L,R=301,NC]
RewriteCond %{HTTP_HOST} ^domain\.co\.kr [NC]
RewriteRule ^(.*)$ https://www.domain.co.kr/$1 [L,R=301,NC]
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
And another one under public_html/public with the default Laravel's htaccess content:
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>
You might ask me why have I two htaccess at two different location. And I wonder the same. The thing is I have done many test and I discovered that putting the www / https rules directly at the root folder kind of worked better. But I might be wrong.
Again sorry if this question has been asked a million time but I couldn't find the answer that would work for me.
Thanks in advance for any bit of help.
The .htaccess file taking care of all the redirects (www or not, https or not) is over-engineered.
It seems like the final domain should always be www.domain.co.kr + SSL so there's no need to use %{HTTP_HOST} as the final domain is not dynamic, or that %{HTTPS}s ^on(s) match to extract s or not.
The order is correct tho: always do all the nitty gritty redirects/http(s) before the framework rewrites.
Because you do that in the parent folder, it's OK. You could put those rules in the same .htaccess file too, but you'd have to put them before the Laravel ones.
I would start with simplifying it:
RewriteEngine On
# Redirect http to https
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,QSA]
# Redirect non-www to www
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule (.*) https://www.domain.co.kr/$1 [R=301,L,QSA]
You'll notice I also added the QSA flag to pass any query string you might have in the original request.
See how you go from there.
Also make sure you always empty your browser cache every time you try something new as redirects are cached.
If it's still not working and you can change the log level on your apache config, check this: http://httpd.apache.org/docs/current/mod/mod_rewrite.html#logging
You'll be able to debug what happens during redirects/rewrites, step by step, to pin point where the actual issue is.

Why does my htaccess code not work?

Could you please explain why my .htaccess code does not work? Whatever the right code is, I'm trying to better understand URL Rewriting and Redirecting and I would appreciate a more verbose/detailed explanation of all syntax and code. Most answers on SO simply state the answer with very little explanation.
# Hypertext Access Directives by Govind Rai
# First rewrite to HTTPS:
# Don't put www. here. If it is already there it will be included, if not
# the subsequent rule will catch it.
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Now, rewrite any request to the wrong domain to use www.
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
###############last two directives that don't work#######################
# hide .html extension govie v1
RewriteCond %{THE_REQUEST} \.html$
RewriteRule ^/[^.]+\.html$ /$1 [NC,R=301,L]
#internal redirect to the right .html file
RewriteCond %{THE_REQUEST} !\.html$
RewriteRule ^/([^.]+)$ /$1.html [L]
I want to understand why the last two rules are not working. When i access a url without the .html extension I get a 404 page not found error, and a url with extension does not rewrite itself without an extension. I've posted the entire file incase there are conflicting rules.
Problem is this condition:
RewriteCond %{THE_REQUEST} \.html$
That condition will never succeed because example value of %{THE_REQUEST} is GET /index.php?id=123 HTTP/1.1. It represents the raw HTTP request as received by Apache.
You can use these rules to fix your issue:
RewriteEngine On
## add www and turn on https in same rule
# if HOST name doesn't start with www. - OR
RewriteCond %{HTTP_HOST} !^www\. [NC,OR]
# if HTTPS is off
RewriteCond %{HTTPS} off
# *capture* hostname part after www in %1
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
# redirect with https://www.%1/... to always apply https and www
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L,NE]
## hide .html extension
# if original request is ending with .html then capture part before .html in %1
RewriteCond %{THE_REQUEST} \s/+(.+?)\.html[\s?] [NC]
# and redirect to %1 (part without .html)
RewriteRule ^ /%1 [R=302,NE,L]
# internally add .html if there a matching .html file in your web root
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+?)/?$ $1.html [L]
References:
Apache mod_rewrite Introduction
Apache mod_rewrite Technical Details
Apache mod_rewrite In-Depth Details
The issue most likely is a pretty simple one: when using rewrite rules inside .htaccess style files the request path is relative, so does not insist on a leading slash. That means you have to modify your rules patterns slightly:
#enable rewriting
Options -Multiviews
RewriteEngine on
RewriteMap /
#internal redirect to the right .html file
RewriteCond %{THE_REQUEST} !\.html$
RewriteCond %{THE_REQUEST} !-f
RewriteCond %{THE_REQUEST} !-d
RewriteRule ^/?([^.]+)$ /$1.html [END]
# hide .html extension govie v1
RewriteCond %{THE_REQUEST} \.html$
RewriteCond %{THE_REQUEST} -f
RewriteRule ^/?([^.]+)\.html$ /$1 [NC,R=301,END]
Instead of completely removing that leading slash I personally like the idea of adding a question mark, so making them optional. This allows to use the same rules inside the http servers host configuration without modification.
I also added the well known twin rules to check if the request does not address a physically existing file or folder. This typically is desired, but you obviously have to decide yourself.
A general hint: you should always prefer to place such rules inside the http servers real host configuration. These .htaccess style files are notoriously error prone, they are hard to debug and really slow down the server, often without reason. They are only provided for situations where you do not have access to that configuration (read: really cheap hosting providers) or if your application needs to write its own rewriting rules (an obvious security nightmare).
${THE_REQUEST} contains The full HTTP request line sent by the browser to the server (e.g., GET /index.html HTTP/1.1) so it will never match \.html$ (since it never ends with .html). Perhaps you can try:
RewriteCond %{THE_REQUEST} \.html\sHTTP
RewriteRule ^([^.]+)\.html$ /$1 [NC,R=301,L]
RewriteCond %{REQUEST_URI} !\.html$
RewriteRule ^ %{REQUEST_URI}.html [L]

Pointing the website http root to a sub folder with htaccess?

How can I use RewriteRule to point the website http root to a sub folder?
I always use the rule below but now after upgrading to the latest wamp server, it does not working anymore. Why?
RewriteRule ^/?$ local/applications/bin/oldsite/index.htm [L,QSA]
I want to point, for instance,
http://mysite.com/ to http://mysite.com/local/applications/bin/oldsite/index.htm
or in localhost wamp server, it should be like this,
http://localhost/mysite/ to http://localhost/mysite/local/applications/bin/oldsite/index.htm
Any ideas?
And also,
http://localhost/mysite/contact.htm to
http://localhost/mysite/local/applications/bin/oldsite/contact.htm
http://localhost/mysite/about.htm to
http://localhost/mysite/local/applications/bin/oldsite/about.htm
EDIT
I managed to point the other pages to the specific locations with the rule below,
RewriteRule ^([a-zA-Z0-9\-]+)\.htm/?$ local/applications/bin/oldsite/$1.htm [L,QSA]
But still I cannot point
http://localhost/mysite/ to http://localhost/mysite/local/applications/bin/oldsite/index.htm
UPDATED
You may try this:
Options +FollowSymlinks
RewriteEngine On
RewriteBase /
#### localhost sets of rules
# No target file, go to index.php
RewriteCond %{HTTP_HOST} localhost [NC]
RewriteCond %{REQUEST_URI} ^/mysite/?$
RewriteCond %{REQUEST_URI} !index\.htm [NC]
RewriteRule . mysite/local/applications/bin/oldsite/index.htm [R=301,L]
# Target file, go to file
RewriteCond %{HTTP_HOST} localhost [NC]
RewriteCond %{REQUEST_URI} ^/mysite/([^\.]+)\.htm [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . mysite/local/applications/bin/oldsite/%1.htm [R=301,L]
#### Live site set of rules
RewriteCond %{HTTP_HOST} (?:www\.)?mysite\.com [NC]
RewriteCond %{REQUEST_URI} !index\.htm [NC]
RewriteCond %{REQUEST_URI} ^/?$
RewriteRule . local/applications/bin/oldsite/index.htm [R=301,L]
The first sets of rules are for the local host and redirect permanently:
http://localhost/mysite/filename.htm
To:
http://localhost/mysite/local/applications/bin/oldsite/filename.htm
When filename.htm is not present in the incoming URL, filename.htm in the substitution URL is always index.htm
The string mysite is assumed to be a fixed string while filename is assumed to be a variable.
The second rule-set is for the web server and redirects permanently only
http://mysite.com/
To:
http://mysite.com/local/applications/bin/oldsite/index.htm
In the last case, if the incoming URL holds any additional path the rule is not applied.
For silent mapping, remove R=301 from [R=301,L].
Copy the above sets of rules into both .htaccess files in the local and remote root directories.
This might get you started (untested):
Check in a condition whether the request does not point to a particular subfolder. If so, redirect the request to a subfolder. You can use in the target if you want. Instead of the HTTP Status 301 you can use another one if more appropriate.
RewriteCond %{REQUEST_URI} !^/(local/applications/bin/oldsite/.*)$
RewriteRule ^(.*)$ http....n/subfolder/%1 [R=301,L]
It seems like you want to make the "oldsite" directory your Document Root - right?

RewriteCond redirect a domain to another except for one script, do the opposite

1) in general, I want everything on www.ABC.com to be redirected to www.XYZ.com
2) EXCEPT when it's
www.ABC.com/this/123([a-z]+).html
... it must Rewrite (NOT redirect) to ...
www.ABC.com/that_script.php?var=123
3) Also EXCEPT: when it's
www.XYZ.com/this/123([a-z]+).html
... it must go (redirect) to ....
www.ABC.com/this/123([a-z]+).html
(so the 2nd rule will apply after that)
EDIT Both domains parked on the same hosting, so sharing the same HTACCESS
EDIT2 Language of the project is PHP
I tried various RewriteCond with %{REQUEST_URI} or %{SCRIPT_FILENAME} but it never works, either saying it's an infinite loop or simply don't take the condition at all.
EDIT3 In PHP, it would looks like that...
if( FALSE !== strstr($_SERVER['HTTP_HOST'], 'ABC.com') && FALSE !== strstr($_SERVER['SCRIPT_FILENAME'], 'that_script') ) {
header("Location: http://www.XYZ.com".$_SERVER['REQUEST_URI'],TRUE,301);
}
if( FALSE !== strstr($_SERVER['HTTP_HOST'], 'XYZ.com') && FALSE === strstr($_SERVER['SCRIPT_FILENAME'], 'that_script') ) {
header("Location: http://www.ABC.com".$_SERVER['REQUEST_URI'],TRUE,301);
}
I want this, but in HTACCESS
Based on what you have above, it will be something to the effect of:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
ReWriteRule ^/this/([a-z0-9]+).html www.ABC.com/that_script.php?var=$1 [PT,L]
RewriteCond %{HTTP_HOST} www.ABC.com$ [NC]
ReWriteRule ^(.*)$ www.XYZ.com [R=301,L]
</IfModule>
This will do the following -
1 - Any traffic hitting http://www.ABC.com/this/<Anything made of Numbers and Letters> will pass through to http://www.ABC.com/that_script.php?var=<Anything made of Numbers and Letters> while continuing to say http://www.ABC.com/this/<Anything made of Numbers and Letters> to the visitor.
2 - Any traffic hitting anything other than what is referenced to #1 will be redirected to www.XYZ.com with a HTTP code of 301 (Moved Permanently).
Remember that you have to be able to put mod_rewrite rules in your .htaccess files. Having the option of AllowOverride FileInfo for the directory would make sure of that.
Use this code in your .htaccess under DOCUMENT_ROOT:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
# Redirect www.xyz.com/this/123([a-z]+).html to www.abc.com/that_script.php?var=123
RewriteCond %{HTTP_HOST} ^(www\.)?xyz\.com$ [NC]
RewriteRule ^this/(123)[a-z]+\.html$ http://www.abc.com/that_script.php?var=$1 [R,L,NC]
# Forward www.abc.com/this/123([a-z]+).html to www.abc.com/that_script.php?var=123
RewriteCond %{HTTP_HOST} ^(www\.)?abc\.com$ [NC]
RewriteRule ^this/(123)[a-z]+\.html$ that_script.php?var=$1 [L,QSA,NC]
# Redirect abc.com to www.xyz.com
RewriteCond %{HTTP_HOST} ^(www\.)?abc\.com$ [NC]
RewriteRule ^ http://www.xyz.com%{REQUEST_URI} [R,L]
Change all R to R=301 once you have verified that it is all working fine.
Also note that I have used first RewriteRule in a way to avoid 1 extra forward (RewriteRule # 2 above).
Have you read the official documentation about mod_rewrite ? All the information you need is in the manual, there is no secret.
RewriteEngine On
RewriteBase /
# Redirect www.xyz.com/this/123([a-z]+).html to www.abc.com/this/123([a-z]+).html.
RewriteCond %{HTTP_HOST} ^www.xyz.com$ [AND]
RewriteCond %{REQUEST_URI} ^/this/123([a-z]+).html$
RewriteRule ^(.*)$ http://www.abc.com/$1 [R=301,L]
# Rewrite www.abc.com/this/123([a-z]+).html to www.abc.com/that_script.php?var=123.
RewriteCond %{HTTP_HOST} ^www.abc.com$ [NC]
RewriteRule ^/this/123([a-z]+)\.html$ /that_script.php?var=123 [L]
# Redirect everything else to www.xyz.com.
RewriteCond %{HTTP_HOST} ^www.abc.com$ [NC]
RewriteRule ^(.*)$ http://www.xyz.com/$1 [R=301,L]

mod_rewrite to remove .php but still serve the .php file?

I just wanted to do a simple thing with mod_rewrite. I have a site which uses .php files, and I wanted to rewrite those to cleaner URLs, and remove the .php. So, files would be www.mysite.com/contact and so on.
This does work how I wanted, but I had expected that it would still serve my contact.php file, but just show the user that they were at /contact rather than contact.php. But, it is looking for a file just called contact, which, is not there.
So, what so I need to do, do still use my contact.php file, but rewrite the URL for the user to /contact ?
Here is what I am using:
SetEnv APPLICATION_ENV development
RewriteEngine on
RewriteBase /
# Always use www.
RewriteCond %{HTTP_HOST} ^mysite\.com$ [NC]
RewriteRule ^(.*)$ http://www.mysite.com/$1 [L,R=301]
# Change urlpath.php to urlpath
RewriteCond %{HTTP_HOST} ^www\.mysite\.com$ [NC]
RewriteRule ^(.*)\.php$ http://www.mysite.com/$1 [L,R=301]
For this solution, I have followed the following rules:
If the user tries to load /something.php they should be externally redirected to /something.
If the user tries to load /something then they should be internally redirected to /something.php.
If the user passed any query string parameters to the URL then these should be preserved through the redirects.
If the user tries to load a different file which really exists on the filesystem (a stylesheet, image etc) then this should be loaded as is.
And here's the final set of mod_rewrite magic:
RewriteEngine on
RewriteBase /
## Always use www.
RewriteCond %{HTTP_HOST} ^mysite\.com$ [NC]
RewriteRule ^(.*)$ http://www.mysite.com/$1 [L,R=301]
# Change urlpath.php to urlpath
## Only perform this rule if we're on the expected domain
RewriteCond %{HTTP_HOST} ^www\.mysite\.com$ [NC]
## Don't perform this rule if we've already been redirected internally
RewriteCond %{QUERY_STRING} !internal=1 [NC]
## Redirect the user externally to the non PHP URL
RewriteRule ^(.*)\.php$ $1 [L,R=301]
# if the user requests /something we need to serve the php version if it exists
## Only perform this rule if we're on the expected domain
RewriteCond %{HTTP_HOST} ^www\.mysite\.com$ [NC]
## Perform this rule only if a file with this name does not exist
RewriteCond %{REQUEST_FILENAME} !-f
## Perform this rule if the requested file doesn't end with '.php'
RewriteCond %{REQUEST_FILENAME} !\.php$ [NC]
## Only perform this rule if we're not requesting the index page
RewriteCond %{REQUEST_URI} !^/$
## Finally, rewrite the URL internally, passing through the user's query string
## using the [qsa] flag along with an 'internal=1' identifier so that our first
## RewriteRule knows we've already redirected once.
RewriteRule ^(.*)$ $1.php?internal=1 [L, QSA]
Your third rule should be the other way around:
# Change urlpath.php to urlpath
RewriteCond %{HTTP_HOST} ^www\.mysite\.com$ [NC]
RewriteCond %{REQUEST_FILENAME} !\.php$ [NC]
RewriteRule ^/?(.*)$ $1.php [L,R=301]
Once the user goes to /contact, it'll load contact.php. The extra RewriteCond is so that if people DO go to contact.php, it won't try to load contact.php.php
As I understand you want the URL to be /contact even if the URL was /contact.php.
You can check for the .php extension and do a redirect to remove it. Use R=301 (as you do).
Then you have to make your server accept the URL without the .php extension. It might actually already do that.
That's what mod_negotiation does. It should be installed by default, but you might have to enable it.
You can also do that with mod_rewrite, but remove the R from the options. It will redirect internally instead of answering with an HTTP redirect.

Categories