Redirect internally to higher directory - .htaccess

I have example.org and foo.example.org pointing to the same directory, /var/www/html/, and want foo.example.org to internally redirect to /var/www/foo/ using only mod_rewrite.
This is what I have so far, but no joy:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^foo [NC]
RewriteRule ^(.*)$ ../foo/$1 [L]
</IfModule>
This gets me 500s due to hitting the limit of 10 internal redirects, but I don't understand why.

The reason for the internal redirect loop is that your only RewriteCond is the host name check. The host name won't change after the internal redirect, and alas, will get triggered when the rules are parsed for the new request. You can solve this by adding a RewriteCond to check if the path already is set to the expected value (i.e. only rewrite requests with the path set to /var/www/html, and skip any other rewrite - as it has already been rewritten).
I'm going to suggest that it might be cleaner to do something like this through mod_vhost_alias, depending on your use case.

Related

SSL .htaccess - Simple Q

I truly hate this file... I just spent 6.5 hours trying to figure this out and with my ADHD dyslexia it's just impossible!!
I have a domain that I bought for SSL for (currently I Have to wait for the ssl for WWW to kick in but for now the domain without WWW works, for example:
https://tomas.com
The .htaccess I have in root is currently:
RewriteEngine On
RewriteCond %{HTTP_HOST} tomas\.com [NC]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://tomas.com/$1 [R,L]
And the code above does in fact activate SSL which is good. The thing is, I have a few files in root domain but one of them called is:
hello.php (located at: "tomas.com/hello.php")
If I go to:
http://tomas.com/hello
I want it to display that file (and in address bar it should say: "http://tomas.com/hello").
Before the SSL I had this code below and it worked (but not anymore):
RewriteRule ^([^/]*)/?(.*)$ $1.php
Any idea how the entire .htaccess is supposed to look like? :/
I'm also same time trying to FORCE it to NOT use www (so if they do it should be redirected to a non WWW url)
Thank you so much in advance!!!!!!!!!!!!
Before the SSL I had this code below and it worked (but not anymore):
RewriteRule ^([^/]*)/?(.*)$ $1.php
Not sure how this "worked" before, it's not complete by itself and does more that simply append a .php extension. You need something to prevent a rewrite loop, since hello.php also matches the pattern ^([^/]*)/?(.*)$.
Try the following instead, after your HTTP to HTTPS redirect.
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
This first checks that the file with a .php file extension exists before internally rewriting to it.
Alternatively, you could instead just enable MultiViews if you aren't doing any other URL rewriting. For example, at the top of your file:
Options +MultiViews
This uses mod_negotiation to basically enable extensionless URLs for everything!

mod-rewrite redirect but prevent direct access

I want to redirect all content to:
www.example.com/public/...
but prevent direct access to
www.example.com/public/file1/
www.example.com/public/file2/
etc
The final URL should be:
www.example.com/file1/
I've tried this for redirecting and it works - but I dont know how to prevent direct access:
ReWriteCond %{REQUEST_URI} !/public/
RewriteRule ^(.*) public/$1 [L]
After spending an inordinate amount of time trying to solve this problem, I found that the solution lies with the under-documented REDIRECT_STATUS environment variable.
Add this to the beginning of your top-level /.htaccess code, and also to any .htaccess files you have under it (e.g. /public/.htaccess):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} !=200
RewriteRule ^ /public%{REQUEST_URI} [L]
</IfModule>
Now, if the user requests example.com/file1 then they are served the file at /public/file1. However, if they request example.com/public/file1 directly then the server will attempt to serve the file at /public/public/file1, which will fail (unless you happen to have a file at that location).
IMPORTANT:
You need to add those lines to all .htaccess files, not just the top-level one in the web root, because if you have any .htaccess files below the web root (e.g. /public/.htaccess) then these will override the top-level .htaccess and users will again be able to access files in /public directly.
Note about variables and redirects:
Performing a redirect (or a rewrite) causes the whole process to start again with the new URI, so any variables that you set before the redirect will no longer be set afterwards. This is done deliberately, because usually you do not want the final result to depend on how you got there (i.e. whether it was via a direct request or via a redirect).
However, for those special occasions where you do want to know how you got to a particular URI, you can use REDIRECT_STATUS. Also, any environment variables set before the redirect (e.g. with SetEnvIf) will still be available after the redirect, but with REDIRECT_ prefixed to the name of the variable (so MY_VAR becomes REDIRECT_MY_VAR).
Maybe you should clarify what's the expected behaviour when user tries to reach the real URL:
www.example.com/public/file1/
If by prevent you mean forbid, you could add a rule to respond with a 403
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !/public/
RewriteRule ^(.*)$ /public/$1 [L]
RewriteCond %{REQUEST_URI} /public/
RewriteRule ^(.*)$ / [R=403,L]
</IfModule>
Update: The solution above doesn't work!
I realized my previous solution always throws the 403 so it's worthless. Actually, this is kinda tricky because the redirection itself really contains /public/ in the URL.
The solution that really worked for me is to append a secret query string to the redirection and check for this value on URL's containing /public/:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !/public/
RewriteRule ^(.*)$ /public/$1?token=SECRET_TOKEN [L]
RewriteCond %{REQUEST_URI} /public/
RewriteCond %{QUERY_STRING} !token=SECRET_TOKEN
RewriteRule ^(.*)$ / [R=403,NC,L]
</IfModule>
This way www.example.com/file1/ will show file1, but www.example.com/public/file1/ will throw a 403 Forbidden error response.
Concerns about security of this SECRET_TOKEN are discussed here: How secure is to append a secret token as query string in a htaccess rewrite rule?
If your URL's are expected to have it's own query string, like www.example.com/file1/?param=value be sure to add the flag QSA.
RewriteRule ^(.*)$ /public/$1?token=SECRET_TOKEN [QSA,L]

.htaccess Redirect from sub.domain.com.au* to www.domain.com.au/URL

I am attempting to redirect a development site that has been indexed by search engines to a specific category in the new live site.
The development site URL was:
http://staging.mydomain.com.au/
There are multiple page url's after the domain so I'd like to redirect all of these to the same new URL.
E.g.
http://staging.mydomain.com.au/essential_grid/
http://staging.mydomain.com.au/feed/
The new url is, where "/portfolio/" is where I need the old URLs redirected to:
http:www.mydomain.com.au/portfolio/
While I'm not receiving any error messages, staging.mydomain.com.au is
not redirecting to www.mydomain.com.au/portfolio/
This is a snippet of what I have in my .htaccess file at present:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_HOST} ^staging.mydomain.com.au$
RewriteRule ^(.*)$ http://www.mydomain.com.au/portfolio [R=301,L]
</IfModule>
Any help would be greatly appreciated.
UPDATE: It seems (from comments) that staging. no longer exists - that's the problem! staging. needs to exist (ie. the DNS must resolve) so that the request gets to your server in order to do the redirect. If staging. does not exist then the initial request will simply fail (the browser will fail to lookup the domain and you'll get a DNS error).
You need to recreate the staging subdomain (even with no files) and then implement the redirect below.
Your RewriteRule actually looks OK - assuming you are wanting to redirect all those URLs to the single /portfolio URL. However, the order should perhaps be changed to have the redirect before the internal rewrite. RewriteEngine only needs to be included once and you don't need RewriteBase in the code you have posted. So, this should be rewritten as:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^staging\.mydomain\.com\.au$
RewriteRule ^ http://www.mydomain.com.au/portfolio [R=301,L]
^(.*)$ is reduced to simply ^ since you don't need to capture the URL for a backreference in the substitution.
I've also removed the other RewriteRule as it doesn't appear to be doing anything?
Also note that 301 redirects are cached by the browser, so make sure that you clear your browser cache between failed attempts. It can be easier to test with 302 temporary redirects for this reason.

htaccess subdomain rewrite without a redirect

Using htaccess Rewrite, I want my url http://*.phoneataxi.com/ (where * is a wildcard, excluding 'www') to show in the address bar as is but get information from http://*.phoneataxi.com/test.php?c=*.
I have tried so many different things but nothing is doing exactly what I need. Most examples are redirecting the subdomain to the '/test.php' file in the address bar which I don't want to do.
I'm trying not to have to create individial subdomains and subdomain folders within my webroot.
Ideas?
I use this htaccess file to make Apache act as a proxy for another host:
IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_HOST} ^ghost\.pileborg\.se$
RewriteRule (.*) http://vps.pileborg.se/ghost/$1 [P]
</IfModule>
It causes all access to http://ghost.pileborg.se/ to be "redirected" to http://vps.pileborg.se/ghost/.
UPDATE (2020)
Some of the answers regarding this topic is very old and no longer work as expected.
After searching for hours on something that actually works, this is what I came up with; edit as you see fit:
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ([a-z0-9]+)\.
RewriteRule ^(.*)$ - [E=BASE:%1]
RewriteCond %{DOCUMENT_ROOT}/%{ENV:BASE}/index.php -f
RewriteRule ^(.*)$ %{ENV:BASE}/index.php [L,NC,QSA]
RewriteCond %{DOCUMENT_ROOT}/%{ENV:BASE}/index.html -f
RewriteRule ^(.*)$ %{ENV:BASE}/index.html [L,NC,QSA]
Breakdown
Make sure that the rewrite module is installed and enabled on your host
first we turn the rewrite engine on and set the path-base
then isolate the subdomain - any letters/numbers before the first dot
set a variable in this runtime environment that contains the subdomain
check if the subdomain folder and index-file exists
if it does exist -then use that file as the request-handler (no redirect)
if it does not exist then the request carries on normally
Flags
The flags used here are explained here, but the ones used above are quite simple:
[L] Last rule, ignore the rest
[NC] No Case, no uppercase/lowercase restrictions
[QSA] I remember this as "Query String Attach" :D

.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.

Resources