RewriteCond to exclude particular directory - .htaccess

I used to have a separate /m directory for mobile (serving m.example.com), but have merged all those files into the main site.
I've set up redirects for all the moved files which are working fine. However, one directory, /games no longer exists in the root directory and I want to stop requests for that directory (e.g. m.example.com/games/game1.php) before they even get to the root.
In the empty m/ directory (only has a .htaccess and ErrorDocument) I have this first:
RewriteRule ^games/ - [L,R=404]
Without it, the request produces an infinite loop on the root domain. Seems to me this should stop the request altogether, but it doesn't.
Then, I have
RewriteCond %{REQUEST_URI} !^games [NC]
RewriteRule (.*) https://www.example.com/$1 [R=301,L]
I expect the request to finish at the first line, RewriteRule ^games/ - [L,R=404] but it currently is going:
http://m.example.com/games/game1.php -> https://m.example.com/my-custom-404-page-on-m.php -> https://www.example.com/my-custom-404-page-on-m.php
So it's correctly flagging the request as a 404, sending it to the custom 404, but not stopping there. The final redirect is still sending it to the main site and the main site doesn't have my-custom-404-page-on-m.php, so returns a 404.
I've tried many other combinations like
RewriteCond %{REQUEST_URI} !^\/games [NC]
RewriteCond %{REQUEST_URI} !^games.* [NC]
RewriteCond %{REQUEST_URI} !^games\/ [NC]
but they all give the same result.
How can I get the failed request to stop in the "m" domain and not go on to the main site?

OK, so I figured it out.
My final RewriteCond should have addressed the file my-custom-404-page-on-m.php, not the /games directory.
Also, it does still need the RewriteRule for games/ directory.
The full solution for .htaccess in "m" domain:
# Even though this directory does not exist, need to include this:
RewriteRule ^games/ - [L,R=404]
# Send ordinary pages on their way, except for the ErrorDocument
RewriteCond %{REQUEST_URI} !^/my-custom-404-page-on-m\.php$ [NC]
RewriteRule (.*) https://www.example.com/$1 [R=301,L]
# Catch any games/ directory 404 cases here
ErrorDocument 404 /my-custom-404-page-on-m.php

Related

Redirect all requests to the same directory

I'm trying to redirect everything in a specific folder to a file inside the same folder for maintenance.
Any type of access in the folder card will have the following rules:
RewriteCond %{REQUEST_URI} /card/?.?
RewriteRule . /card/maintenance.html [R,L]
But I'm getting a weird redirect error, like an endless loop of redirects. I have to redirect deeper in the folder, I can't access the folders outside card.
You need to exclude maintenance.html otherwise that gets redirected as well. Try:
RewriteCond %{REQUEST_URI} !maintenance.html
RewriteCond %{REQUEST_URI} ^/card/
RewriteRule ^ /card/maintenance.html [R,L]

.htaccess infinite loop on 404 in subfolders

I got a little problem concerning a project I'm working on.
I want to maintain only one .htaccess file in the root folder of this project. It is modular, so there are many different subfolders. My current .htacccess looks as follows:
ErrorDocument 401 /401.php
ErrorDocument 404 /404.php
RewriteEngine On
#strip www from domain
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
#ignore existing files and directories
RewriteCond %{REQUEST_FILENAME} -f [NC,OR]
RewriteCond %{REQUEST_FILENAME} -d [NC]
RewriteRule .* - [L]
# Check if query string exists
RewriteCond %{QUERY_STRING} ^$
# Check that the request is not for an existing file
RewriteCond %{REQUEST_FILENAME} !-f
The problem is that every 404 error in a subfolder leads to an infinite loop because it looks for i.e. http://mydomain.tld/modules/index.php?p=404 instead of http://mydomain.tld/index.php?p=404 .
I know I could hardcode the URL in my .htaccess, but the problem is that it's kind of a community-hosting platform, where the community is specified dynamically via the subdomain and I want to keep the request in that specific subdomain.
Is there any possible way to force the .htaccess to use the index.php in the root-folder without giving the absolute url?
Thanks in advance!

Root folder change (.htaccess)

In my "public_html" directory I have the following structure:
- root
- index.html
- blog
- index.html
- lab
- index.html
- wp
- (WORDPRESS FILES)
The "lab" and "wp" directories are just subdomain directories ("http://lab.tomblanchard.co.uk" and "http://wp.tomblanchard.co.uk") which work fine.
Basically I want the main domain ("http://tomblanchard.co.uk") to point to the "root" directory without any actual redirecting, for example, I want "http://tomblanchard.co.uk" to point to the "index.html" file within the "root" directory, I want "http://tomblanchard.co.uk/blog" to point to the "index.html" file within the "root/blog" directory and so on.
I have kind of achieved this with the following code in my ".htaccess" file:
# Add directives
RewriteEngine on
# Remove ".html" extension from URLs
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html
# Change root directory to "root" folder
Options +FollowSymLinks
RewriteCond %{REQUEST_URI} !(.*)root
RewriteRule ^(.*)$ root/$1 [L]
The only problem is that things like "http://tomblanchard.co.uk/root/" and "http://tomblanchard.co.uk/root/blog/" still work when really they shouldn't even be able to be accessed (404).
If anyone has any idea on how to sort this or has a stronger method of doing this it would be greatly appreciated.
Update
Finally got it working how I wanted it after hours of researching, I used the following:
# Add directives
RewriteEngine on
# Change root directory to "root" folder
RewriteCond %{THE_REQUEST} ^GET\ /root/
RewriteRule ^root/(.*) /$1 [L,R=301]
RewriteRule !^root/ root%{REQUEST_URI} [L]
The order of directives in mod_rewrite is important, as each rule sees the output of the previous rule as its input to test. You need to do 3 (or possibly 4) things, in order:
Deny access to any URL beginning /root/ (we have to do this first, else everything will be denied!)
It's generally good practice to ensure each URL has only one valid form, so URLs which do specify .html should cause a browser redirect to the non-.html form. This needs to happen before other rewrites, otherwise you can't tell the difference between a .html from the browser and one you've added virtually.
Look up any URL not denied above in the /root/ directory, rather than the configured DocumentRoot
Look up any URL not pointing at a directory under the URL + .html, if that file exists. This has to come after other rewrites, or the "file exists" check will always fail.
# General directives
Options +FollowSymLinks
RewriteEngine on
# Deny URLs beginning /root/, faking them as a 404 Not Found
RewriteRule ^root/ [R=404]
# Additional rule to strip .html off URLs in the browser
RewriteRule ^(.*)\.html$ $1 [R=permanent,L]
# Rewrite everything remaining to the /root sub-directory
# (Host condition was in your post originally, then edited out; this is where it would go)
RewriteCond %{HTTP_HOST} ^(www\.)?tomblanchard\.co\.uk$
RewriteRule ^(.*)$ root/$1
# Handle "missing" ".html" extension from URLs
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html
PS: Note my careful language to describe (internal) rewrites, as opposed to (browser) redirects: the rule you have is not removing .html from anything, it is adding it, thus allowing the page to be accessed if someone else removes it. Since you are often modifying both within a set of rules, it's important to keep clear in your head the distinction between the URL the browser has requested, and the virtual URL Apache will ultimately serve.
You are not defining any rule to block /root address so how do you want to block it when there is nothing to do that?
Try this:
# Add directives
RewriteEngine on
RewriteCond %{REQUEST_URI} .root [NC]
RewriteRule (.*) / [L,R=404]
# Remove ".html" extension from URLs
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html
# Change root directory to "root" folder
RewriteCond %{HTTP_HOST} ^tomblanchard.co.uk$ [NC,OR]
RewriteCond %{HTTP_HOST} ^www.tomblanchard.co.uk$
RewriteCond %{REQUEST_URI} !.root
RewriteRule (.*) /root/$1 [L,R=301,QSA]
This is not tested so if it wouldn't work, play around with it to get your need.

htaccess for multiple subdomains from folders

I am dealing with following problem:
I have one main domain "example.com" and multiple subdomains:
one.example.com
two.example.com
three.example.com
etc. on server.
I have content for this subdomains in folders:
./one/ -> one.example.com
./two/ -> two.example.com
./three/ -> three.example.com
etc.
So to serve content from these folders to subdomains, I use following htaccess file:
RewriteCond %{HTTP_HOST} ^one.example.com [NC]
RewriteCond %{REQUEST_URI} !^/one/.*
RewriteRule ^(.*) /one/$1 [L]
It works fine, but my content for subdomains is also accessable from URL:
one.example.com/one/my-content
such as
one.example.com/my-content
etc. So it is duplicite.
This is one problem I need to solve.
Second is, that content for example.com is accessable from
whatever.example.com
(a.example.com, b.example.com etc.)
so again duplicite.
So my question is: how to redirect/disable URLs that are creating duplicite?
Thanks a lot, I've tried a lot of versions of code, but with no effect.
I solved this issue by redirecting all requests to a subdomain to that folder and all requests to the base domain to another, like this:
RewriteCond %{HTTP_HOST} ^one\. [NC]
RewriteRule (.*) /one$1 [L]
RewriteCond %{HTTP_HOST} ^two\. [NC]
RewriteRule (.*) /two$1 [L]
RewriteRule (.*) /zero$1
It seems to work, but I'm having my URL modified on the browser too. How do I avoid this from happening?
For your first issue, you can add a rule, that redirects any requests to that folder and withing that directory to a page that does not exists (so that it throuws a 404 error)
RewriteCond %{HTTP_HOST} ^one\.example\.com$ [NC]
RewriteCond %{REQUEST_FILENAME} ^one/
RewriteRule . /notexists.html [L]
For your second issue, this should not happen since when you ask for a.example.com/folder/file.html it gets redirected internaly to a.example.com/a/folder/file.html (there is no way to get the content in the parent directory of 'a' )

redirecting subdomain to subfolders not containing an index.php with .htaccess

i am getting a 500 internal server error with the following:
RewriteCond %{HTTP_HOST} ^data\.mysite\.com$ [NC]
RewriteRule ^(.*)$ data/$1 [L,QSA]
-----------------???
when i replace the RewriteRule line by the following:
RewriteRule ^(.*)$ data/index.php?r=$1 [L,QSA]
it works , but in real case i will not have an index.php in the folder, i will have folders containing images...
Any Idea??
original question here
Your rewrite rules are looping, each time the URI is rewritten, it is reapplied to all the rules until the rules don't change the URI. So when you request /something, the rewrite rule gets applied and the URI is changed to /data/something, then it is resent through the rewrite engine, then it gets rewritten to /data/data/something then /data/data/data/something etc. Eventually mod_rewrite will reach its recursion limit and return a 500 server error. You can try a few things to end the loop, assuming you really only want a single /data/ to be appended in the beginning. You can add one of the following before your RewriteRule
RewriteCond %{REQUEST_URI} ^/data
or
RewriteCond $1 ^/data

Resources