Migration HTTP to HTTPS except 1 directory - .htaccess

I would like to migrate a site from HTTP to HTTPS except one directory.
It's not working .... first of all, is it possible to code this?
#https exept directory dir2
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} !dir2[NC]
RewriteRule^https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

RewriteCond %{REQUEST_URI} !dir2[NC]
You are missing a space delimiter before the flags argument, so this will never match the intended directory. It should read:
RewriteCond %{REQUEST_URI} !dir2 [NC]
RewriteRule^https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
You are also missing two spaces surrounding the pattern. So this will again never match anything. So, this should read:
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Spaces are delimiters in Apache config files.
However, this can be improved, as you don't need the additional condition if you just want to exclude a single directory. You should use the RewriteRule pattern instead:
RewriteCond %{HTTPS} off
RewriteRule !^dir2 https://%{HTTP_HOST}%{REQUEST_URI} [NC,L,R=301]

Related

htacces 2 variables issues

BEFORE I installed SSL things were working perfectly!! Here is the code I have in my root webserver .htaccess file:
Options +MultiViews
RewriteEngine On
RewriteCond %{HTTP_HOST} andrea\.com [NC]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://andrea.com/$1 [R,L]
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
It works and it does exactly what I want it to do. So if I go to for example:
www.andrea.com/account
it accesses "www.andrea.com/account.php". Which is what I want.
I do however have a folder in root called "products". There is another ".htaccess" file in that folder and I don't know which of these 2 must be changed to make the following thing below work.
When you go to this url:
http:____/products/view/Hello/Goodbye
I want it to access "view.php" in the 'products' folder and in that php file I could do this:
$id = $_GET["id"]; // This would have "Hello"
$cat = $_GET["cat"]; // This would have "Goodbye"
And this works well when I use this htaccess in the "products" folder:
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 %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/?(.*)$ /products/view.php?id=$1&cat=$2
The problem with this code above is, if I go to:
http:____/products/Hello/Goodbye
I want it to access the "index.php" that is in "products" folder. But instead it goes to "view.php" instead!! It's like the htaccess code above forced all to go to view.php (which should only be done if I have the "view/____" in the url.
I want the url above to go to "index.php" in the "products" folder and in that file I should be able to access ID and CAT variables.
Any ideas of what to change in my .htaccess file? Sorry I spent over 2 hours I don't understand a single line at the bottom of my code but it doesn't work :/
Options +MultiViews
First off, you should disable MultiViews. In my answer to your earlier question, my suggestion to use MultiViews was strictly an "alternative" method in the context of your question. You cannot use both methods (mod_rewrite and MultiViews) to work with extensionless URLs. And since you are now wanting to do more things and pass parameters, MultiViews will only create conflicts. (MultiViews will likely "win" and no parameters get passed.)
Also, do you specifically need the additional .htaccess file in the /products subdirectory? It will be (arguably) easier to have a single .htaccess file in the document root. This will avoid having to repeat the HTTP to HTTPS redirect (although you've not actually included an HTTP to HTTPS redirect in the subdirectory .htaccess file?).
# /products/.htaccess
RewriteRule ^([^/]*)/?(.*)$ /products/view.php?id=$1&cat=$2
This directive matches both view/Hello/Goodbye and Hello/Goodbye, which explains why everything is being written to your view.php script. However, it's not actually doing what you say either - which is puzzling. If you request /products/view/Hello/Goodbye then it will rewrite the request to /products/view.php?id=view&cat=Hello/Goodbye - which is not the intention (unless MutliViews is enabled, in which case no parameters will be passed at all).
You need to actually check for views in the requested URL-path before attempting to rewrite to views.php. And if views is not present then rewrite to index.php instead. This "conditional branching" can be achieved by simply arranging the directives in the order of "more specific" rules first.
For example, in your root .htaccess file try the following. (And remove the /products/.htaccess file altogether.)
# Ensure that MultiViews is disabled
Options -MultiViews
RewriteEngine On
# HTTP to HTTPS canonical redirect
RewriteCond %{HTTP_HOST} example\.com [NC]
RewriteCond %{SERVER_PORT} 80
RewriteRule (.*) https://example.com/$1 [R=301,L]
# Abort early if the request already maps to (or looks like) a file or directory
RewriteCond %{REQUEST_URI} \.\w{2,4}$ [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# 1. Rewrite "/products/view/<id>/<cat>" to "/products/view.php?id=<id>&cat=<cat>
RewriteRule ^(products/view)/([^/]*)/?(.*) $1.php?id=$2&cat=$3 [L]
# 2. Rewrite "/products/<id>/<cat>" to "/products/index.php?id=<id>&cat=<cat>
RewriteRule ^(products)/([^/]*)/?(.*) $1/index.php?id=$2&cat=$3 [L]
# 3. Extensionless URLs for other requests
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
The order of the 3 rules above is important. The most specific rule is first. Including the L flag to prevent further (unnecessary) processing.
Note that, as per your original directives, for a request of the form /products/view/Hello/Goodbye (or /products/Hello/Goodbye), the Hello/Goodbye part is entirely optional and will naturally result in the id and cat URL parameters being set, but empty.
Also, as per your original directives, a request of the form /products/view/Hello/Goodbye/foo/bar/baz will result in the cat URL parameter being set to Goodbye/foo/bar/baz (anything that follows the initial path segment).
You do not necessarily need to check that a request maps to a file or directory (which is relatively expensive) if you make your regex more specific and only match what you need to match. For example, your regex /([^/]*)/?(.*) currently match pretty much anything. But if your <id> and <cat> variables can only consist of lowercase letters (for example) then this could avoid the need for the filesystem checks.
Other notes:
Do you need to check the hostname in the HTTP to HTTPS redirect? Do you host multiple domains? Otherwise the condition that checks against the HTTP_HOST server variable is not required.
You can use the following rule to rewrite /products/Hello/Goodbye to /products/index.php .
RewriteRule ^Hello/GoodBye/?$ /product/index.php?id=hello&cat=Goodbye [L,NC]
Here is your complete /product/.htaccess .
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]
#rewrite /products/Hello/GoodBye to /products/index.php
RewriteRule ^Hello/GoodBye/?$ /products/index.php?id=Hello&cat=Goodbye [L,NC]
###################
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/?(.*)$ /products/view.php?id=$1&cat=$2

.htaccess to redirect to new website structure

I have changed the website URL structure and I want to redirect my users
The problem
The new structure is very different, and more strict.
OLD
1 - https://example.com/serie-tv
2 - https://example.com/serie-tv/1845578-the-walking-dead
3 - https://example.com/serie-tv/1845578-The-Walking-Dead/seasons/1
4 - https://example.com/serie-tv/1845578-the-walking-dead/seasons/1/episodes/1
NEW
1 - https://example.com/browse?type=series
2 - https://example.com/titles/1845578
3 - https://example.com/titles/1845578/season/1
4 - https://example.com/titles/1845578/season/1/episode/1
A redirection from https://example.com/serie-tv/1845578-the-walking-dead/seasons/1
to
https://example.com/titles/1845578-the-walking-dead/season/1 will not work.
Need to redirect just to https://example.com/titles/1845578/season/1
For now I only managed to redirect everything under
https://example.com/serie-tv /.....
to
https://example.com/browse?type=series
with this code:
RewriteCond %{HTTP_HOST} ^example\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$
RewriteCond %{REQUEST_URI} !^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteRule ^serie\-tv\/?(.*) "https\:\/\/example\.com\/browse?type=series" [R=301,L]
A slight complication comes about because you have seasons and episodes (with an s) in the old URL structure and season and episode (no s) in the new URL structure, so you can't use a general solution that simply copies the URL-path.
RewriteCond %{HTTP_HOST} ^example\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com$
If you only have a single domain then these conditions are superfluous.
RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$
RewriteCond %{REQUEST_URI} !^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
For now, we can ignore these as well. cPanel will automatically inject these as required when auto-renewing your SSL certs.
For now I only managed to redirect everything under ...
I assume you don't want to redirect "everything" since your preceding example URLs do not state this?
RewriteRule ^serie\-tv\/?(.*) "https\:\/\/example\.com\/browse?type=series" [R=301,L]
There is unnecessary backslash escaping here that affects readability. There is no need to escape literal hyphens (-) and slashes in the RewriteRule pattern. And in the substitution string (which is an "ordinary" string, not a regex), there is no need to escape the colon (:), slash (again) and dot. These "literal" characters carry no special meaning in the context they are used. (This is typical output having used cPanel's redirection feature - which will often put them in the wrong place as well.)
Try something like the following instead, near the top of your .htaccess file:
RewriteEngine On
# Redirect "/serie-tv"
RewriteRule ^serie-tv$ /browse?type=series [R=302,L]
# Redirect "/serie-tv/1845578-the-walking-dead"
RewriteRule ^serie-tv/(\d+)-[^/]+$ /titles/$1 [R=302,L]
# Redirect "/serie-tv/1845578-the-walking-dead/seasons/1"
RewriteRule ^serie-tv/(\d+)-[^/]+/seasons/(\d+)$ /titles/$1/season/$2 [R=302,L]
# Redirect "/serie-tv/1845578-the-walking-dead/seasons/1/episodes/1"
RewriteRule ^serie-tv/(\d+)-[^/]+/seasons/(\d+)/episodes/(\d+)$ /titles/$1/season/$2/episode/$3 [R=302,L]
\d is a shorthand character class for digits (the same as [0-9]) and \d+ matches 1 or more digits.
$1, $2 and $3 are backreferences to the captured groups in the RewriteRule pattern. It's more efficient to test what you can in the RewriteRule pattern instead of using a preceding condition that checks the REQUEST_URI server variable.
Note that these are currently 302 (temporary) redirects. Only change to 301 (permanent) when you have tested that they work OK - in order to avoid caching issues.
You will need to clear your browser cache before testing.
Aside: The old URL structure, that includes the title maybe better from an SEO / useability perspective?
I think this should do what you need.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} /serie-tv$ [NC]
RewriteRule ^(.*)$ browse?type=series [R=301,L]
RewriteCond %{REQUEST_URI} /serie-tv/([0-9]*)\-([^/]*)/?(.*)? [NC]
RewriteRule ^(.*)$ titles/%1/%3 [R=301,L]

Replace all occurrences of a word with another in .htaccess

I need to change one word which is there in all URLs linking to my site.
I tried with the following rule but it works fine only when the word is the first one in URL
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteCond %{REQUEST_URI} ^/foo(?:/)?(.*)$
RewriteRule ^[/]?foo[/]?(.*) /bar/$1 [R=permanent,L,NE]
When I add wildcard entries to REQ_URI, output is not proper, I am not sure how to handle replacements. www.example.com/abc/def/foo/ghi is rewirtten as www.example.com/bar/abc/def
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteCond %{REQUEST_URI} ^(.*)/foo(?:/)?(.*)$
RewriteRule ^(.*)[/]?foo[/]?(.*) /bar/$1 [R=permanent,L,NE]
How do I correct the rewrite rule ?
RewriteRule ^(.*)/foo/(.*)$ $1/bar/$2 [R=301,L]
RewriteRule ^foo/(.*)$ bar/$1 [R=301,L]
This assumes foo is a folder name. Generally when setting something like this up you want to have some sort of delimiter (in this case the slashes) so that, for example, "food" doesn't become "bard".

Skip a directory with htaccess

RewriteCond %{HTTP_HOST} ^(www.)?example\.com$ [NC]
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
So i have this in my htaccess file to take care of the trailing slash problem . It redirects you every time you add a trailing slash on a url.
The issue here is the fact there is one directory where it needs the trailing slash or it breaks. How do I add a exception for a directory like http://www.example.com/com/ to this rule..
The simplest to understand approach is to use an additional condition:
RewriteCond $1 !=com
RewriteCond %{HTTP_HOST} ^(www.)?example\.com$ [NC]
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
This works because the order of execution is rule.regexp, cond1, cond2, rule.substitution. Hence the $1 variable is available to the (new) cond1. You could also use a negative assertion on your regexp.
Incidentally, the http://%{HTTP_HOST}/ is assumed in the case of a [R=301] for http. Why do you not want to remove / for other host aliases?

Creating a mod_rewrite rule in an htaccess file

I am trying to create a mod_rewrite rule to direct people to a sub-folder. Currently the code looks as follows:
RewriteEngine On
RewriteCond %{HTTP_HOST} abcsite.com$ [OR,NC]
RewriteCond %{HTTP_HOST} ^!www\.abcsite\.*$
RewriteCond %{REQUEST_URI} !^/abc/.*$
RewriteRule (.*)$ /abc/$1 [L]
The redirect works if the user types www.abcsite.com, but not if they type abc.com. Is there something that I am missing or should do differently to make sure the user goes to the correct folder (regardless of how they type the URL)?
Side note: The htaccess file that I am dealing with is a Joomla file, so all contents of it deal with another Joomla site. I appreciate the help.
Because you have conditions for that.
RewriteCond %{HTTP_HOST} abcsite.com$ [OR,NC]
RewriteCond %{HTTP_HOST} ^!www\.abcsite\.*$
RewriteCond %{REQUEST_URI} !^/abc/.*$
All above rules will pass only its abcsite.com
You add following rules also then it work for abc.com too.
RewriteCond %{HTTP_HOST} abc.com$ [OR,NC]
RewriteCond %{HTTP_HOST} ^!www\.abc\.*$
RewriteCond %{REQUEST_URI} !^/abc/.*$
RewriteRule (.*)$ /abc/$1 [L]
There's a stray ! in your second condition. A ! in front of the pattern means that the condition is true when the regex doesn't match (like in the third condition). A ! inside the pattern is just a literal symbol.
The host conditions should be something like:
RewriteCond %{HTTP_HOST} ^abcsite\.com$ [OR,NC]
RewriteCond %{HTTP_HOST} ^www\.abcsite\.com$ [NC]
And in fact, they can be joined into a single condition (note, no [OR] here):
RewriteCond %{HTTP_HOST} ^(www\.)?abcsite\.com$ [NC]
Your third condition is intended to prevent redirect loops (/foo → /abc/foo → /abc/abc/foo → …). What it says is that the rule isn't applied if the request URL starts with /abc/. However, your actual redirect is an internal redirect: if a user accesses abcsite.com/foo, the server internally rewrites this to /webroot/abc/foo, but REQUEST_URI stays the same, /foo.
The reason this doesn't cause a redirect loop as it is is likely rewrite rules in abc/.htaccess which override this one once the redirect is done.
What should be checked instead in the third condition is the path matched by the rewrite rule:
RewriteCond $1 !^abc/
RewriteRule (.*) /abc/$1 [L]

Resources