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.
Related
i am new to .htaccess usage and tried to learn through online resources but however i write it the rules negate each other and am having a hard time writing a good enough .htaccess file below is my current .htaccess file which works fine for some pages like removing extensions and rewriting subdomains please check below
## Flag for GoDaddy
Options +MultiViews
RewriteBase /
## Remove extensions
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !=f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
## Redirect from extensions to non-extensions
RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
RewriteRule ^ /%1 [R=301,NE,L]
## Redirect Pages
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^post/([a-zA-Z0-9-/]+)$ /post.php?ps=$1
RewriteRule ^([a-zA-Z0-9-/]+)$ post-files.php?ps=$1 [L,QSA]
## Server Only
## Redirect from www - non-www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://$1/$1 [R=301,L]
## SSL Redirect
## RewriteEngine On
## RewriteCond %{HTTPS} ≠On
## RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
## Create Error Pages
ErrorDocument 404 /errors/404.html
ErrorDocument 403 /errors/403.html
ErrorDocument 500 /errors/500.html
## Redirect non-existing pages to index.php
Options +SymLinksIfOwnerMatch
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
Above is the .htaccess am currently using and i got it through tutorials from youtube it works good and redirects files.php to files only which am happy with but
as you can see above this line RewriteRule ^post/([a-zA-Z0-9-/]+)$ /post.php?ps=$1 and the line below it are not passing through the ps but they show 404 page
i want the results to be domain.com/post-file-slug to go to exactly file domain.com/post-file.php?ps=post-slug-here for rule RewriteRule ^([a-zA-Z0-9-/]+)$ post-files.php?ps=$1 [L,QSA]
and
domain.com/post/post-slug-here to go to exactly domain.com/post.php?ps=post-slug-here for rule
RewriteRule ^post/([a-zA-Z0-9-/]+)$ /post.php?ps=$1
I was working on this for 2 days now hopefully fix it soon. Thanks
## Flag for GoDaddy
Options +MultiViews
In what way is this a "flag for GoDaddy"? Enabling MultiViews will cause the ps URL parameter not to be passed to the post.php script. You need to ensure that MultiViews is disabled for the later rewrites to work as intended. ie.
Options -MultiViews
MultiViews (part of mod_negotiation) essentially enables extensionless URLs. It will result in a request for /post/post-slug-here to be "rewritten" to /post.php/post-slug-here before your mod_rewrite directive is processed, so it never matches and never rewrites the request to include the ps URL parameter.
## Remove extensions
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !=f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
## Redirect from extensions to non-extensions
RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
RewriteRule ^ /%1 [R=301,NE,L]
It is currently MultiViews that is allowing your extensionless URLs to work. The first condition (RewriteCond directive) above is incorrect. It should be !-f (not a file), not !=f (does not equal "f" - always true). However, this is still "wrong", as you need to check that the .php file exists before rewriting the request. If you simply rewrite all requests that do not map to a file (which is what you are trying to do here) then the later rewrites to post.php, post-files.php and index.php will not be processed as intended.
The regex \s/+(.+?)\.php[\s?] in the second condition is not strictly correct as it will result in a malformed redirect if .php occurs in the query string when it is omitted in the URL-path. eg. A request for /foo?bar.php would result in a redirect to /foo?bar when there should be no redirect at all in this instance. The regex needs to capture the URL-path only, so change the subpattern (.+?) to ([^?]+) instead.
These two rules are also the wrong way round. The external redirect should be first. As a general rule, external redirects should always go before internal rewrites.
It should be like this instead:
## Remove extensions
## Redirect to remove ".php" extension
RewriteCond %{THE_REQUEST} \s/+([^?]+?)\.php[\s?] [NC]
RewriteRule \.php$ /%1 [R=301,NE,L]
# Rewrite to append ".php" extension if corresponding ".php" file exists
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^.]+)$ $1.php [L]
You should already be linking to the file without the .php extension. The redirect to remove the .php extension is for SEO only when changing an existing URL structure.
No need to backslash-escape a literal dot when used inside a regex character class. The NC flag was superfluous here.
## Redirect Pages
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^post/([a-zA-Z0-9-/]+)$ /post.php?ps=$1
RewriteRule ^([a-zA-Z0-9-/]+)$ post-files.php?ps=$1 [L,QSA]
RewriteCond directives only apply to the first RewriteRule directive that follows. So, the second rule above is processed unconditionally - is that the intention?
In fact, those two condition are probably superfluous. The regex would already appear to exclude actual files since the regex excludes dots. And do you need to be able to access filesystem directories directly?
The character class [a-zA-Z0-9-/] is "confusing". The last hyphen is seen as a literal hyphen (which is presumably the intention), but at first glance it can look like a range specifier (as used earlier in the character class). To avoid confusion when matching a literal hyphen inside a character class, either backslash-escape it, or move it to the first or last character in the character class. eg. [a-zA-Z0-9/-].
You are also missing the L flag from the first rule. (You've included it on the second.) Do you also need the QSA flag? (ie. Are you expecting additional URL parameters on the initial request?)
Having revised the "extension removal" rules above, this does not matter so much, but these rules that rewrite the request to post.php and post-files.php should really be above the "extension removal" rules.
## Redirect from www - non-www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://$1/$1 [R=301,L]
This rule is incorrect and in the wrong place. Canonical redirects (www to non-www and HTTP to HTTPS) should generally be above other rules. As mentioned above, redirects before rewrites.
But this rule is also wholly incorrect. $1 is a backreference to the first captured subpattern in the RewriteRule, so http://$1/$1 will naturally result in a malformed redirect. The first backreference should be %1 (to the last matched CondPattern) to match the requested hostname. Ordinarily, you should also be redirecting to HTTPS here, not HTTP. For example, the rule should read:
:
RewriteRule (.*) https://%1/$1 [R=301,L]
The ^ and $ surrounding the RewriteRule pattern are superfluous since regex is greedy by default.
## SSL Redirect
## RewriteEngine On
## RewriteCond %{HTTPS} ≠On
## RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
Although commented out, it is also incorrect. It needs to go before the other rewrites. It should go at the top of the file if implementing HSTS or after the www to non-www redirect if not (and minimising the number of redirects).
The CondPattern in the preceding condition should be !on, not ≠On (which is wholly invalid on two counts... ≠ is not valid and the comparison is case-sensitive. HTTPS will always be lowercase.)
You are also missing the R=301 and L flags.
No need for a capturing group in the RewriteRule pattern, since this is not being used in the substitution string. ^ would suffice (and be more efficient) instead of (.*).
## Create Error Pages
ErrorDocument 404 /errors/404.html
ErrorDocument 403 /errors/403.html
ErrorDocument 500 /errors/500.html
For readability, you should define your custom error documents at the top of the file. (Technically, it doesn't matter.)
## Redirect non-existing pages to index.php
Options +SymLinksIfOwnerMatch
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
For readability you should define the Options together at the top of the file (with -MultiViews). For example:
Options -MultiViews -Indexex +SymLinksIfOwnerMatch
(Disabling Indexes - auto-generated directory listings - is a good idea.)
You do not need to repeat the RewriteEngine directive. (Only the last instance of this directive does anything.) It is logical to place this rule near the top of the file, before your first mod_rewrite directive. (Although technically, the position of this directive in the file does not actually matter.)
Aside: You should be consistent in the prefix you use on your internal rewrites. On some rules you include the slash prefix (eg. /post.php), and on some you have omitted it (post-files.php). You have defined RewriteBase / (which isn't strictly required here as it happens) - RewriteBase only applies to relative substitution strings (ie. when the slash prefix is omitted).
UPDATE:
also i have file i want to exclude like 404.php in root directory from how do i exclude somefiles from the redirect. when i sent ajax to backend php file it redirected to homepage and failed to retrieve data.
To exclude specific files you would add a rule like the following, after the canonical redirects:
# Exclude "/404.php" from stripping the ".php" extension
RewriteRule ^404\.php$ - [L]
Generally, once you go extensionless for .php files you should be extensionless everywhere. So, there should be no unexpected redirects. The redirect is really only for SEO.
With regards to your AJAX requests, if you are making POST requests, then you could simply exclude all POST requests from further processing. For example:
# Prevent further processing of POST requests to ".php" files
RewriteCond %{REQUEST_METHOD} POST [NC]
RewriteRule \.php$ - [L]
Alternatively (or as well as), if your AJAX requests are setting a custom HTTP request header then you can check for this as well.
Summary
Bringing the above points together, it should look like this:
## Disable MultiViews and Indexes
Options -MultiViews -Indexes +SymLinksIfOwnerMatch
## Create Error Pages
ErrorDocument 404 /errors/404.html
ErrorDocument 403 /errors/403.html
ErrorDocument 500 /errors/500.html
RewriteEngine On
RewriteBase /
#### Canonical redirects
## SSL Redirect
## RewriteCond %{HTTPS} !on
## RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]
## Redirect from www - non-www
## >>> CHANGE TO "HTTPS://"
RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
RewriteRule (.*) http://%1/$1 [R=301,L]
#### Rewrite Pages
RewriteRule ^post/([a-zA-Z0-9/-]+)$ post.php?ps=$1 [QSA,L]
RewriteRule ^([a-zA-Z0-9/-]+)$ post-files.php?ps=$1 [QSA,L]
#### Exceptions
## Exclude "/404.php" from stripping the ".php" extension
RewriteRule ^404\.php$ - [L]
## Prevent further processing of POST requests to ".php" files
RewriteCond %{REQUEST_METHOD} POST [NC]
RewriteRule \.php$ - [L]
#### Remove extensions
## Redirect to remove ".php" extension
RewriteCond %{THE_REQUEST} \s/+([^?]+)\.php[\s?] [NC]
RewriteRule \.php$ /%1 [R=301,NE,L]
## Rewrite to append ".php" extension if corresponding ".php" file exists
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^.]+)$ $1.php [L]
## Redirect non-existing pages to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
I have a url like this:
http://www.localhost.com/code_category/computers/
I want to change this url to:
http://www.localhost.com/category/computers/
I don't need url redirection.
My current htaccess file looks like this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
You only want to redirect code_category to categoryexternally and keep the path as it is internally so, try this :
RewriteCond %{THE_REQUEST} !\s/+category/ [NC]
RewriteRule ^code_category/(.*)$ category/$1 [R=302,L,NE]
RewriteRule ^category/(.*)$ code_category/$1 [L]
The above will redirect any request containscode_category/whatever to category/whatever externally and keep the internal path as it is .
If you want only request contains code_category/computers/ change it to this :
RewriteCond %{THE_REQUEST} !\s/+category/computers/ [NC]
RewriteRule ^code_category/computers/(.*)$ category/computers/$1 [R=302,L,NE]
RewriteRule ^category/computers/(.*)$ code_category/computers/$1 [L]
test it , if it is fine change 302 to 301 for permanent redirection.
Note: clear your browser cache then test it.
.htaccess file
Add this code
RewriteEngine on
RewriteCond %{HTTP_HOST} ^localhost.com [NC,OR]
# without redirect
# RewriteRule ^/code_category/computers/$ category/computers/
RewriteRule ^/category/computers/$ code_category/computers/
# redirect method
# RedirectMatch 301 ^/code_category/computers/$ category/computers/
RewriteEngine On enables mod_rewrite.
RewriteCond %{HTTP_HOST} shows which URLs we do and don't want to run through the rewrite.
In this case, we want to match example.com.
! means "not." We don't want to rewrite a URL that already includes folder1, because then it would keep getting folder1 added, and it would become an infinitely long URL.
[NC] matches both upper- and lower-case versions of the URL.
RewriteRule defines a particular rule.
The first string of characters after RewriteRule defines what the original URL looks like. There's a more detailed explanation of the special characters at the end of this article.
The second string after RewriteRule defines the new URL. This is in relation to the document root (html) directory. / means the html directory itself, and subfolders can also be specified.
For Reference click here
Hope this helps!
My site is HTTPS enabled and all the pages are served using HTTPS only. Client now has the requirement where he wants to show static pages like about-us, termsofus as HTTP pages and not as HTTPS. This means that even if the user tries to open about-us page as HTTPS it should redirect to HTTP version of about-us.
My .htaccess code is as follows:
Options -Indexes
<IfModule mod_rewrite.c>
RewriteEngine on
#RewriteCond %{HTTPS} off
#RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} !^\/about-us
RewriteCond %{REQUEST_URI} !^\/termsofus
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} \/about-us [OR]
RewriteCond %{REQUEST_URI} \/termsofus
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
</IfModule>
Problem: Whenever I open HTTP/HTTPS version of about-us page it keeps on redirecting me to index.php.
For example: https://example.com/about-us to https://example.com/index.php
The site uses PHP YII framework.
Use THE_REQUEST variable instead of REQUEST_URI. THE_REQUEST variable represents original request received by Apache from your browser and it doesn't get overwritten after execution of some rewrite rules.
Options -Indexes
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteCond %{THE_REQUEST} !\s/+(about-us|termsofus) [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
RewriteCond %{HTTPS} on
RewriteCond %{THE_REQUEST} \s/+(about-us|termsofus) [NC]
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
Make sure to clear your browser cache before testing this change.
anubhava's answer already addresses the problem and provides a good solution. I thought I'd just provide some additional explanation as to what was happening with your stated example with reference to your original code:
For example: https://example.com/about-us to https://example.com/index.php
Given a request for https://example.com/about-us:
This matches your second rule (HTTPS is "on" and about-us is requested) and redirects to http://example.com/about-us (ie. back to HTTP).
The redirected request (ie. http://example.com/about-us) now matches the last rule and gets internally rewritten to index.php (the front-controller).
However, in per-directory .htaccess files (directory context) "the rewritten request is handed back to the URL parsing engine" and the process effectively starts over. The REQUEST_URI server variable is also updated to hold the rewritten URL ie. /index.php.
On the second pass through the .htaccess file the request (now rewritten to http://example.com/index.php) matches your first rule (HTTPS is "off" and the request is not /about-us or /termsofus) so the request is redirected (a second time) to https://example.com/index.php. (The internal rewrite is effectively changed into an external redirect.)
The redirected request (now https://example.com/index.php) does not match any rules in your .htaccess file, so passes through unchanged. Page is served.
If you check the network traffic, you should see the two external redirects mentioned above.
Another possible solution is to use the END flag (Apache 2.4+ only) on the last RewriteRule. This effectively ends the URL rewriting process, so the process stops at step #2. Although I would still favour anubhava's solution and check against THE_REQUEST instead, which works on Apache 2.2 and will still work should you introduce additional rewrites.
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]
If want to redirect all non-www requests to my site to the www version. All I need to do is add the following code to my .htaccess file.
RewriteCond %{HTTP_HOST} ^mydomain\.com [NC]
RewriteCond %{REQUEST_URI} !^/subfolder
RewriteRule .* http://www.mydomain.com%{REQUEST_URI} [R=301,L]
The problem is that when I write for example mydomain.com/products-1 (hidden URL for mydomain.com/products?category=1), all parameters become visible, even though they are specified on the .htaccess file, and I get an output url (after the redirect) of www.mydomain.com/products-1?category=1
How can I fix this? Is there any kind of problems with the .htaccess code above?
Try Changing your RewriteRule:
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteCond %{REQUEST_URI} !^/subfolder
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]
I prefer this because it will catch all *.domain.com. If that is not what you want, then use your original HTTP_HOST rule.
If my logic is working this morning, this rule should rewrite any requests that do not match:
www.example.com
and do not contain
/subfolder
to
www.domain.com/URI