Redirect based on rules and error type htaccess - apache

I have been trying to piece together my .htaccess file, I have not found a lot of information about what I am trying to accomplish or if I am over thinking it.
I am using the following to disable directory browsing it works but I would like to redirect it to a custom 404 error page I have created.
# Disable Directory Browsing
Options All -Indexes
Deny access to directories or files I am using the following
####
# Deny access to certain directories that SHOULD NOT be exposed.
####
RewriteRule ^error/ - [L,R=403]
RewriteRule ^assets/ - [L,R=403]
RewriteRule ^plugins/ - [L,R=403]
RewriteRule ^libraries/ - [L,R=403]
RewriteRule ^includes/ - [L,R=403]
RewriteRule ^bootstrap.php - [L,R=404]
all of these work as it should but I want to redirect to a custom error page in my script folder
example.com/errors/
All i have found is this
ErrorDocument 404 /errors/error-404.html
but have been unsuccessful in getting any of the errors redirected to the one I created.

Without seeing the actual response you are seeing or your full .htaccess file, my guess would be that you are blocking access to the /errors directory that contains your custom error documents. The error documents themselves need to be publicly accessible (although there are tricks you can employ to block access and serve an appropriate HTTP status code).
If you block access to the error document then Apache will fallback to the default Apache response with an additional message along the lines of:
Additionally, a "4xx/5xx error" error was encountered while trying to use an ErrorDocument to handle the request.

Related

How to redirect 404 errors (and 403) to index.html with a 200 response

I am building a static website that uses JS to parse a URL in order to work out what to display.
I need every URL to actually open index.html where the JS can pull apart the path and act accordingly.
For example http://my.site/action/params will be parsed as an action with some parameters params.
Background, this will be served from AWS S3 via CloudFront using custom error redirection - and this works fine on AWS.
I am, however, trying to build a dev environment under Ubuntu running apache and want to emulate the redirection locally.
I have found a couple of pages that come close, but not quite.
This page shows how to do the redirect to a custom error page on the server housed in a file called "404". As 404 is the actual error response code, the example looks a bit confusing and I am having trouble modifying the example to point to index.html.
The example in the accepted answer suggests:
Redirect 200 /404
ErrorDocument 404 /404
which I have modified to:
Redirect 200 /index.html
ErrorDocument 404 /index.html
However this returns a standard 404 Not Found error page.
If I remove the Redirect line, leaving just the ErrorDocument line, I get the index.html page returned as required, but the https status response is still a 404 code where I need it to be a 200.
If I leave the Redirect line as per the example I actually get the same result as my modified version, so I suspect this is the line that is incorrect, but I can't figure it out.
(I'm using the Chrome Dev Tools console to see the status codes etc).
I think I have found a solution using Rewrite rules instead of error docs.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
The key I was missing in this approach seems to be not including an R=??? status response code at the end of the rewrite rule. It took me a while to find that!
As it uses mod_rewrite rather than defining error pages I assume that the mechanism is different to how CloudFront does it, but for my dev system needs it seems that the result is the same - which means I can work on the site without having to invalidate the CloudFront cache after every code change and upload.

Apache 2.4 Internal mod_rewrite is not working

I have the following excerpt in my .htaccess file:
RewriteEngine On
# Whether RewriteBase is commented does not appear to have an impact on my problem
# RewriteBase /
RewriteRule ^admin/(.*) members/$1 [L]
The idea is that the pages in /admin load from the /members directory, since certain features are duplicated between them, so that I don't have to duplicate my code. (There are other directives in the file that are related to a CMS system, and those are working as expected.)
On the current Apache 2.2 server, everything works fine. My client's webhost wants to upgrade to a server with Apache 2.4, and on the test server the rewrite rule fails. Instead of loading the page, it just displays "File not found."
All other rules are executed as expected, it's just that one that fails. I have tried adding/removing / characters and removing [L] from the rule, it always fails. I tried adding [R] to send the redirect to the browser, but even that failed. But if I change the url to the same filename but in the members directory, then the file loads successfully.
Being able to change one directory name to another seems like a pretty basic function of mod_rewrite. What am I missing?

What are ways to block direct access to files on apache but allow them through scripts?

If I type in the direct path to any of the content in my server directory I can see and download the file without being logged in. (example I have a directory foo with a file bar.jpg in it. If I type into the search bar "ip:port/foo/bar.jpg I can see the picture without needing to go through the pages I created). I know it would be difficult to access but if it can happen it eventually will. Is there a way that allows my php script to access files and display them in a webpage but not allow any direct access to the content on my server when typed in? I have tried .htaccess files and directly altering the server config in apache, my access looks like this:
<Directory "C:\xampp\htdocs\RootFolder\Login System">
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?Family [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ - [NC,F,L]
</Directory>
The problem here is that it randomly blocks some images in my page while allowing others through:
GET http://localhost/Family/IMG_2436.jpg 403 (Forbidden)
I have been bashing my head in trying to get this to work so that if someone types in a direct link they get an access denied while accessing through my php page would just show the picture or file. Is there any way to do this? ps I'm using a windows base

mod_rewrite rules for existing files

I am defining mod_rewrite rule that will rewrite all requests to my /application.php if requested file not exists, and won't do any rewriting otherwise. It is simple:
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule .* application.php [PT]
There is only one problem with the code. Assume I have foo.html file. Then requests like:
http://example.com/foo.html/some/other/string
will fall with 404 error.
Why?
will fall with 404 error. Why?
Because that URL doesn't exist. It's looking for the file string in the folder /foo.html/some/other and it's not there.
The behaviour that you want to exploit using the http://example.com/foo.html/some/other/string URL structure - treating the first entry as a file name, and the rest as a parameter to it - is called "pathinfo". It has nothing to do with mod_rewrite, but will be available if you enable the following in your Apache configuration:
AcceptPathInfo On
it looks like that setting is currently turned to "off" for you.
If you enable it, the part after the file name will be available to foo.html - in PHP, it would be in the
$_SERVER["PATH_INFO"]
variable.
Because this method doesn't require the rewrite module to be active, this is sometimes called "the poor man's mod_rewrite" - it works fine, but isn't quite as pretty as flexible as "real" rewriting.

How do I force Apache to simply redirect the user and ignore the directory structure?

Ok, so this problem recently arose and I don't know why it is happening; it's actually two problems in one...
0. My .htaccess file, for reference. (EDITED)
Options -Indexes +FollowSymLinks
RewriteEngine On
RewriteBase /
ErrorDocument 400 /index.php?400
ErrorDocument 401 /index.php?401
ErrorDocument 403 /index.php?403
ErrorDocument 404 /index.php?404
ErrorDocument 410 /index.php?410
ErrorDocument 414 /index.php?414
ErrorDocument 500 /global/500.php
RewriteCond %{HTTP_HOST} !^$ [NC]
RewriteRule .* index.php [L]
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(.*\.)?(animuson)\.(biz|com|info|me|net|org|us|ws)/.*$ [NC]
RewriteRule ^.*$ - [F]
1. My 'pictures' folder is following the hard path instead of the redirect.
I have no idea WHY it is doing this. It's really bugging me. The 'pictures' folder is a symbolic link to another place so that I can easily upload files to that folder without having to search through folders and such via my FTP account, but that's the only thing I use it for. However, when I visit http://example.com/pictures my htaccess sees it as accessing that other folder, which is restricted, and throws a 403 error rather than redirecting to index.php and displaying the page like normal.
I figured it has something to do with that specific folder being a symbolic link causing it to act oddly, but I have determined that my rules are not being applied to folders at all. If I visit folders such as 'css' and 'com' which are folders in the web root, it displays a 404 error page and adds the '/' to the end of the URL because it's treating it as a directory. It also does the same 403 error for my 'images' directory which is set up in the same fashion.
So, the question here is how do I modify my RewriteRule to apply to the directories as well? I want everything accessed via the web to be redirected back to index.php while maintaining the full access path in the address bar, why is it not working? (I'm pretty sure it was working fine before.)
Here's a small chart to show the paths they're following...
example.com/pictures -> pictures/ -> /home/animuson/animuson-pictures -> 403
example.com/com -> com/ -> 404
example.com/test -> index.php
example.com/ -> index.php
example.com/images -> images/ -> /home/animuson/animuson-images -> 403
example.com/css -> css/ -> 404
EDIT: Following information added.
Apache is processing the structure of the directory first. It's determining if the path exists based on what was typed into the address bar. If someone types in a folder name that happens to exist, it will redirect the user to the path with the "/" at the end of the URL signifying that it's a directory. For the 'pictures' directory explained above, the user does not have permission to access that folder so it is redirecting them to a 403 Access Denied page rather than simply showing the page that is supposed to be displayed there via the RewriteRule above. My biggest question is why is Apache processing the directory first and how do I make it stop doing that? I would really love an answer to this question.
2. Why is my compression not working? (EDIT: This part is fixed.)
When analyzing my site through a web optimizer, it keeps saying my page isn't using web compression, but I'm almost 100% positive that it was working fine before under the same settings. Can anyone suggest any reasons why it might not be working with this set up or suggest a better way of doing it?
Where is this .htaccess file situated? At the root or in the pictures directory?
1) You're using Options -Indexes which will deny access to directory listings. This is handled by /index.php?403 which in turn will redirect to /403. (I confirmed this by manually going to /index.php?403) I don't see any other rules in the posted .htaccess that are supposed to affect this. So this either happens because either index.php or some other .htaccess file or server rule makes that redirect.
You might also want to check the UNIX file permissions of the directory in question.
2) According to this aptimizer, http://www.websiteoptimization.com/services/analyze/, compression is indeed enabled for html, js and css files, as specified in the rules. My bet is that the optimizer is being stupid and does one of these three things:
1)) Complaining about images not being compressed. (It's generally a bad idea to compress images because they're typically already compressed and the extra CPU load typically isn't worth it since the net gain is so small. So your rules are OK in this regard.)
2)) It might think that DEFLATE doesn't count as compression, and wants you to use GZip.
3)) It might also react to the externally included StatCounter js file, which is not compressed. (And there's not much you can do about that.)
After a while of deliberating on Apache's IRC channel, I was finally able to figure out the real reasoning behind this on a fluke. I just happened to be looking at the directory structure using ls -l and noticed that all of the symbolic links had somehow has their permissions changed to animuson:animuson from the root:root original. I tried to run a simple chown root:root on them and it had no effect, so I deleted them all and recreated them and the problem has gone away. I don't really have any idea why the permissions made any different in this scenario but the solution worked and everything is okay now. I've also added a DirectorySlash Off to my .htaccess file to get rid of the slashes after folders that exist, just to make it look all that much nicer.