.htaccess cans and can'ts - .htaccess

I am very new to the idea of .htaccess and thought that it was what you used to do something like turn this:
http://www.domain.com/some/ugly/url/here.html
into this:
http://www.domain.com/niceurl
I was just told by my ISP that in order to get that to happen, no, it's done by putting the document into the web root folder. That .htaccess isn't used at all.
Does anyone know if this is true? I see a lot of examples about what .htaccess DOES but not so much about what it can't do. Somehow I thought this was all that was needed.
Lastly, if someone types in www.domain.com/niceurl what will happen? Don't I need to have that linked (if not by htaccess, how?!) to the location of the actual file?
Thank you for any and all help. I realize that .htaccess questions abound but they're hard to pick through for the layperson and I'm hoping to answer this specific question.

Here's what I believe should be an answer you want, put the block below to your .htaccess
Answer:
## Enabling Apache's Mod_rewrite module.
RewriteEngine On
# Following line is required if your webserver's URL is not directly related to physical file paths (just / for root, e.g. www.domain.com/)
RewriteBase /
# Restricts rewriting URLs only to paths that do not actually exists
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# Redirect www.domain.com/bar to www.domain.com/foo
Redirect 301 /bar /foo
# Internally load the long URL without changing URL in address bar
RewriteRule ^foo/?$ http://www.domain.com/some/ugly/long/thing/here.html [L,NC]
As a result, www.domain.com/bar will be redirected to www.domain.com/foo and /foo will internally load http://www.domain.com/some/ugly/long/thing/here.html
FYI:
Your website's URL doesn't have to be directly related to physical file paths. Your URL's segment can be served as alias to your URL's parameters. for e.g,
http://www.domain.com/index.php?key1=value1&key2=value2
can be represented as
http://www.domain.com/value1/value2
Note: you need to implement a server side script to be served as a
router to manipulate the URL segments.
For more information about using .htaccess, check this out
Ref: http://htaccess-guide.com/
.htaccess files can be used to alter the configuration of the Apache Web Server software to enable/disable additional functionality and features that the Apache Web Server software has to offer. These facilities include basic redirect functionality, for instance if a 404 file not found error occurs, or for more advanced functions such as content password protection or image hot link prevention.
Below is a few examples,
# Custom Error Pages for Better SEO,
# for e.g, to handle 404 file not found error
ErrorDocument 404 http://www.domain.com/404page.html
# Deny visitors by IP address
order allow,deny
deny from 122.248.102.86
deny from 188.40.112.210
allow from all
# Redirects
Redirect 302 /en/my-dir/my-page.html /en/my-path/example.html
# Disallow some silly bots from crawling your sites
RewriteCond %{HTTP_USER_AGENT} (?i)^.*(BlackWidow|Bot\\ mailto:craftbot#yahoo.com|ChinaClaw|Custo|DISCo|Download\\ Demon|eCatch|EirGrabber|EmailSiphon|EmailWolf|Express\\ WebPictures|ExtractorPro|EyeNetIE|FlashGet|GetRight|GetWeb!|Go!Zilla|Go-Ahead-Got-It|GrabNet).*$
RewriteRule .* - [R=403,L]
# Setting server timezone
SetEnv TZ America/Los_Angeles
# trailing slash enforcement,
# e.g, http://www.domain.com/niceurl to http://www.domain.com/niceurl/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !#
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://www.domain.com/$1/ [L,R=301]

Enable mod_rewrite and .htaccess through httpd.conf (if not already enabled) and then You can use this code in your DOCUMENT_ROOT/.htaccess file:
RewriteEngine On
RewriteRule ^niceurl/?$ some/ugly/url/here.html [L,NC]
This will allow you to use http://domain.com/niceurl in your browser and it will internally load http://domain.com/some/ugly/url/here.html without changing URL in browser.
If you also want to force redirection from ugly URL to pretty URL then add this redirect rule just below RewriteEngine On line:
RewriteCond %{THE_REQUEST} \s/+some/ugly/url/here\.html [NC]
RewriteRule ^ /niceurl [R=302,L,NE]

Related

How do I redirect to all pages to be a subdirectory of another website but keep the URLs the same?

I have a website that has been built at say montypython.netlify.app
The client has their main website at holygrail.com and they want holygrail.com/resources to show the contents of montypython.netlify.app but keep the URL the same. Which means that it should continue to show holygrail.com/resources in the search bar.
This also means that any pages from montypython.netlify.app should appear are subdirectories of holygrail.com/resources
Example:
montypython.netlify.app/about should appear as holygrail.com/resources/about
I am guessing this has to do with editing the .htaccess at holygrail.com but what rewrite/redirect rules can I reference? There are a lot of URLs so is there a wildcard approach I can use?
This is what I've tried:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^holygrail\.com$ [NC]
RewriteRule ^resources/(.*)$ https://montypython.netlify.app/$1 [R=301,L]
</IfModule>
You can use the [P] proxy flag of mod_rewrite.
Using [P] flag instructs mod_rewrite to handle the request via mod_proxy. Therefore, you must enable mod_proxy to use flag.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^holygrail\.com$ [NC]
RewriteRule ^resources/(.*)$ https://montypython.netlify.app/$1 [P]
</IfModule>
with this code snippet, all pages to be a subdirectory resources will be served from https://montypython.netlify.app/ without a 301 redirection.
Maybe your issue is with the line:
RewriteCond %{HTTP_HOST} ^holygrail\.com$ [NC]
Maybe you need to try to do something like
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/$
RewriteRule ^resources/(.*)$ https://montypython.netlify.app/$1 [R=301,L]
</IfModule>
I have worked on projects in the past with similar objectives. I don't believe you can accomplish this with redirects. The suggestion about using a reverse proxy would be the most well aligned with your requirements, but there is another option that may also be useful. Some DNS providers offer "DNS Cloaking" or "Stealth Redirects". This can be configured so that requests for holygrail.com will display a frame containing the content for montypython.netlify.app. Could you use the same approach for the /resources sub-directory, so that holygrail.com/resources delivers a frame that loads montypython.netlify.app?
The drawback to this is the address bar will not change as you navigate inside the frame, e.g. navigating to montypython.netlify.app/resources/about will still show holygrail.com/resources in the address bar, because it is displaying the address of the frame.

500 error for html site on shared hosting, is my .htaccess syntax wrong?

First time here. I'm actually an Industrial & Systems Engineer from Mexico, trying to become a self-taught Web Developer/Graphic Designer. I'M SORRY if my english is flawed & for being such a noob, especially if my question was already asked by someone else, or whatever. (I did search questions, though)
I just finished (out of a bought html template) the 1º stage of the website (& everything design wise) of a new company (which is my client): https://www.starhauss.com/
The site works fine... considering what was requested of me, considering it's the 1º stage, it has minor flaws... I think.
ANYWAY...
I need to do (& tried) several things with .htaccess for my client, ASAP:
Redirect to custom 404
Declare Spanish language (the site will soon have an english version on /en/ directory)
Block sensible Server info
Disable directory listings
Remove www from urls
Remove html file extensions from urls
Block hidden files from appearing
Block "risky" files from appearing
Force https on the urls
Check & correct simple spelling errors on urls
I researched the Apache guides & everything, from different sources & I came up with my own .htaccess file, but I'm not sure if the syntax is wrong, or if I need to contact the respective Hosting Support Guys so they allow my file to be executed, because when it's uploaded (RIGHT NOW IT'S NOT UPLOADED) with CyberDuck to the root directory encoding text via US-ASCII with 755 file permissions, accessing my site results in a 500 Internal Server Error. I don't know what modules are on by default on the server of the shared hosting company, but of what I understand, they do work with the Apache Platform.
My .htaccess code is the next
# redirect not found
ErrorDocument 404 /404.html
# declare language for multilingual sites, adding a .htaccess file for each language subdirectory
DefaultLanguage es
# prevent server from outputing sensible information
ServerSignature Off
# disable directory listings, only when on
Options -Indexes
# requirement to change urls & such
RewriteEngine On
# use in subdirectories if rewrite rules are not working properly
# RewriteBase /
# mod_rewrite.c wrapper works mainly with WordPress & such
# <IfModule mod_rewrite.c>
# remove www from urls
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
# remove html file extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.html [NC, L]
# block hidden files
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule "(^|/)\." - [F]
# </IfModule>
# block risky files
<FilesMatch "(^#.*#|\.(bak|config|dist|fla|inc|ini|log|psd|sh|sql|sw[op])|~)$">
Order allow,deny
Deny from all
Satisfy All
</FilesMatch>
# force https
<IfModule mod_headers.c>
Header set Strict-Transport-Security max-age=16070400;
</IfModule>
# check & correct url spelling errors, useful for SEO
<IfModule mod_speling.c>
CheckSeplling On
</IfModule>
So, what do you think guys? Should it work? Is something wrong with the code syntax, the order or whatever? Is something missing Server Side for the file to work & if so, how can I know, if I have no access to the Httpd.Conf? Should I get in contact with the shared hosting support for them to allow my file?
RewriteRule ^([^\.]+)$ $1.html [NC, L]
You have an erroneous space in the RewriteRule flags argument. This will result in a 500 Internal Server Error and if you look at your server's error.log you will see an error reported like "RewriteRule: bad flag delimiters".
Whenever you get a 500 error (which is just a generic server response), you need to check the server's error log for the details of that error.
In this case, [NC, L] should be [NC,L]. Although the NC flag is superfluous here, so [L] is sufficient.
<IfModule mod_speling.c>
CheckSeplling On
</IfModule>
You've spelt CheckSpelling wrong. (This would also trigger a 500 error response.)
Force https on the urls
# remove www from urls
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
You're not actually "forcing HTTPS" anywhere.
The above only removes www on HTTP only. Why are you specifically checking that the request is not HTTPS in the above www to non-www redirect and redirecting to HTTP, not HTTPS?
You could change the above to the following in order to remove www on HTTP and HTTPS (canonicalising HTTPS at the same time):
# Remove www (redirect to HTTPS)
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
And add an additional rule to force HTTPS (however, see note below about HSTS*1):
# Force HTTPS
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# force https
<IfModule mod_headers.c>
Header set Strict-Transport-Security max-age=16070400;
</IfModule>
This doesn't strictly "force https".
This "HSTS header" instructs the browser to always request HTTPS, once the user has visited the site over HTTPS. It does nothing if the user has only visited the site over HTTP (hence the requirement to first redirect/force the user to HTTPS - see above). However, this is not complete - you need to redirect on the same host first (*1ie. reverse the two redirects above) and also set the header on the 301 redirect that removes www over HTTPS (this directive does not). And ideally you should avoid sending the header over plain HTTP (although that does not strictly matter, as the browser will simply ignore it).
I would avoid setting HSTS initially, until your site is working correctly over HTTPS. You should consider HSTS as a one-way trip, it is problematic to backtrack on this (max-age=16070400 will persist this for 6+ months for anyone who visits over HTTPS).
See the following related question on the CodeReview stack regarding HSTS implementation: https://codereview.stackexchange.com/questions/250805/hsts-recommendations-in-htaccess
Order allow,deny
Deny from all
Satisfy All
These are Apache 2.2 directives and are formerly deprecated on Apache 2.4. I assume you are using Apache 2.4 (Apache 2.2 was EOL almost 2 years ago). You should use the Apache 2.4 directives instead:
Require all denied

htaccess for root pages / but not sub-directories or sub-domains

trying to rewrite URL strings only for pages that reside in the root, removing the page extension for cosmetic reaons. For example:
www.site.com/page.html ==> www.site.com/page
www.site.com/about.html ==> www.site.com/about
Using this code currently:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^([^.]+\.com) [NC]
RewriteRule (.*) http://www.%1/$1 [R=301,L]
BUT, I don't want the rule to modify sub-directiories or sub-domains. For example I also have:
clientA.site.com (which is mapped to www.site.com/clientA), which I need to not be remain unchanged. Right now it is sending that page (client.site.com/index.html) to a page not found.
Your rule doesn't affect subdomains. There must be other rules causing the 404 not found response.
If you want to restrict requests to the root pages, you can specify that with an appropriate pattern by excluding slashes in the request URL path
# exclude directories
RewriteCond %{REQUEST_FILENAME} !-d
# allow top level request URLs only
RewriteRule ^[^/]*$ http://www.%1/$0 [R,L]
Never test with 301 enabled, see this answer
Tips for debugging .htaccess rewrite rules
for details.

.htaccess to fake subdomain

I have a requirement where in I want to give users of my site their personal url.
Something like "http://abc.example.com" and when any user types this url in browser it should open this link "http://www.example.com/index/sub-domain?username=abc"
So I tried writing and trying many codes and finally was successful with below code but problem is it redirects. I want an internal redirection. URL address window should remain as "http://abc.example.com".
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^.*$ index.php [NC]
RewriteCond %{HTTP_HOST} !^www.
RewriteCond %{HTTP_HOST} ^([a-z]+)\.example.com$
RewriteRule ^(.*)$ http://www.example.com/index/sub-domain?username=%1
</IfModule>
I am not sure if It is possible or not ? Any advice or help will be of great help. Also can anyone suggest me some .htaccess tutorial.
If you do not specificy the R flag on your RewriteRule, mod_rewrite normally performs an internal rewrite. However, since you are using an absolute URL as your rewrite target, it has to be the exact same host, otherwise an external redirect will be issued.
If you really wish to internally redirect to another host, you should check out mod_proxy.

How do I rewrite a URL so that the rewrite can be typed into the URL bar?

I have the following page: www.domain.com/index.php?route=information/contact and I'd like to rewrite it so that it shows up as: www.domain.com/contact, but there's more...
What's important, is that when someone types in www.domain.com/contact, it redirects them to www.domain.com/index.php?route=information/contact, which in turn, is rewritten as www.domain.com/contact.
I appreciate any help! Thanks.
Edit: To clarify
I want users to be able to enter www.domain.com/contact and be redirected to www.domain.com/index.php?route=information/contact.
However once redirected, I'd like a purely aesthetic rewrite so that www.domain.com/index.php?route=information/contact shows up as www.domain.com/contact (the same as what they typed in.)
Is this possible?
Edit: My .htaccess file currently...
Options +FollowSymlinks
# Prevent Directoy listing
Options -Indexes
# Prevent Direct Access to files
<FilesMatch "\.(tpl|ini)">
Order deny,allow
Deny from all
</FilesMatch>
# SEO URL Settings
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)\?*$ index.php?_route_=$1 [L,QSA]
RewriteCond %{QUERY_STRING} ^route=common/home$
RewriteCond %{REQUEST_METHOD} !^POST$
RewriteRule ^index\.php$ http://www.domain.com/? [R=301,L]
### Additional Settings that may need to be enabled for some servers
### Uncomment the commands by removing the # sign in front of it.
### If you get an "Internal Server Error 500" after enabling, then restore the # as this means your host
doesn't allow that.
# 1. If your cart only allows you to add one item at a time, it is possible register_globals is on. This
may work to disable it:
# php_flag register_globals off
Try these rules in your .htaccess file:
Options +FollowSymlinks -MultiViews
RewriteEngine on
RewriteCond %{THE_REQUEST} ^GET\s/+index\.php [NC]
RewriteCond %{QUERY_STRING} ^route=information [NC]
RewriteRule . /warranty? [L,NC,R=301]
RewriteRule ^warranty$ /index.php?route=information/contact [L,NC]
L will make sure that user's URL in browser doesn't change and redirection happens internally.
Your question is extremely unclear, and I suspect that inexperience is to blame.
With the following rule:
RewriteRule /?(.*) index.php?route=information/$1
the location bar will read "/contact" but index.php will be invoked via an internal rewrite.
With a small modification:
RewriteRule /?(.*) index.php?route=information/$1 [R]
the location bar will read "/index.php?route=information/contact" and index.php will be invoked, after the redirect.
As always, the rule should follow the appropriate RewriteCond so as to avoid rewriting if an actual file is requested.
AFAIK, you can't make the address bar show a different address than the one that the page was loaded from. If you want the user to see www.domain.com/contact in the address bar when viewing the page, you need to make the server actually return the page content (not a redirect) when that URL is requested.
I think you might be misunderstanding URL rewriting: it's not for changing what the user sees in the address bar, it's for changing what the server sees when a request arrives from the user. If you create a rewrite rule that changes /foo to /bar, then when the user types /foo in their browser, the server will treat it as a request for /bar.
What you want, I think, is that when the user types www.domain.com/contact in their browser, the server should treat it as a request for www.domain.com/index.php?route=information/contact, but the browser should still show the pretty URL that the user typed. The way to do that is to simply rewrite /contact to /index.php?route=information/contact on the server. No redirect is needed; the user simply requests the pretty URL, and the server handles the request based on the equivalent ugly one and sends back the resulting page.

Resources