Apache 404 url not working - apache

I have a few problems with our company website. My colleague left the .htaccess file inside the _control directory like this:
# Virtual site directory
#
# This script lets us make use of default
# versions of files used in a typical site.
# When a request on the site is made for a file
# that doesn't exist, instead of a 404 we rewrite
# the path to /_control/site/
#
# Any file in the directory this script is in will
# take precedence over this script, so this script
# only comes into play if the file does not exist.
# First, set up URL rewriting
Options +FollowSymLinks
RewriteEngine On
# Add trailing slash for directories
# TODO: fix if site not in root dir (e.g. DEV server)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !.+\.(php|js|css|gif|jpg|jpeg|png)$ [NC]
RewriteCond %{REQUEST_URI} !.*/$
RewriteRule ^(.*)$ /$1/ [L,R=301]
# This Apache mod_rewrite rule checks to see
# if the requested file exists, if it doesn't
# then we rewrite to the respective site location.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !^.*/_control/(admin|common).*$
RewriteCond %{REQUEST_FILENAME} !^.*/_control/site/.*$
RewriteRule ^(.*)$ site/$1 [L]
The structure of my application looks like:
Everything was working OK but about a week ago, our mysite.com/admin and 404 page started redirecting to the hosting company's website. DaveG has already answered first part of the problem here: https://stackoverflow.com/a/26013322/1933380 and I was able to get the virtual directories working. I am still having problems with the 404 page. Am I missing something or making a mistake?

What you are doing now, is telling the webserver to look for all non-existing pages and directories in another folder (_control). This does not give a solution for typo's, non-existing pages etc. If you want to solve this, you could use:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !^.*/_control/(admin|common).*$
RewriteCond %{REQUEST_FILENAME} !^.*/_control/site/.*$
RewriteRule ^(.*)$ site/errhandler.php?file=$1 [L]
and make a file called errhandler.php, which displays a custom 404-page and (for example) give possible alternatives based on a database search or whatever. You could then use $_GET['file'] to display the original filename.

Related

.htaccess matches files even without extension in URL

.htaccess
RewriteEngine On
# If directory, redirect to root
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ / [R,L]
# Don't show something.json
#RewriteCond %{REQUEST_FILENAME} -f
RewriteRule something\.json$ / [R,L]
# If not file or directory, go to the router
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /subfolder/router.php [L]
# Any other existing files get served normally
We can ignore the first two rules, they work. The problem is in the 3rd part/rule.
htaccess file is here:
https://subdomain.sitename.com/subfolder/.htaccess
I need any non-directory and non-file addresses to go to /subfolder/router.php.
I have a html file on the server:
https://subdomain.sitename.com/subfolder/sub2/filename.html
I want the URL:
https://subdomain.sitename.com/subfolder/sub2/filename
to map to /subfolder/router.php, since filename doesn't exist on the server (only filename.html exists).
But it serves/shows the filename.html file/page instead of mapping to /subfolder/router.php. Address bar still shows just filename without .html.
It works fine on my localhost, but not on the online server I uploaded the files to. I don't have access to the config files of the server.
I've read online, and looks like I'm on a virtual host, maybe?
I've tried:
Options -MultiViews (gives error)
AcceptPathInfo off (doesn't help)
RewriteCond %{REQUEST_FILENAME}.html -f (nope)
... some other desperate ways of matching
Is there any way to force RewriteCond %{REQUEST_FILENAME} !-f to not match extensions of files on the server when they are not in the URL?
Or at least somehow fix the problem?
I'm losing my mind right now, after hours of trying things and reading online. Any help would be greatly appreciated.
Okay, after some thinking and trying things out, I solved it by changing:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /subfolder/router.php [L]
to
RewriteRule \.html$ /subfolder/router.php [L]
I'm not entirely happy, but it works for now, as the router.php file checks for file existence and uses a whitelist of files.

Configure `htaccess` to open contained `index` file when navigating to an existing directory

I'd like the following three rules in my site's htaccess file, but only the last two are working.
In writing rule one below, I've tried a number of codes, combinations, and orders, cobbled from postings elsewhere (taking care to commenting the other rules in testing). All I've gotten for it are 500, 404, and 403 errors.
Any help as to how to accomplish this, please?
#
# RULE ONE (FAIL)
# Navigation to a directory will open its contained 'index' file.
# This is so I can give visitors `mysite.com/project`,
# rather having to give them `mysite.com/project/index.html`.
#
#
# RULE TWO (GOOD)
# Navigation to a non-existent directory will redirect to a file
# of the same name and location.
# This is so if a visitor mistakenly goes to `mysite.com/somepage/`,
# they'll get to `mysite.com/somepage.html`.
#
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=301,L]
#
# RULE THREE (GOOD)
# Navigation to a file without an extension will append an '.html' extension.
# This is so I can give a visitor `mysite.com/somepage`,
# rather than `mysite.com/somepage.html`.
#
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.html [NC,L]
You're getting redirect loops because apache will always redirect the browser to the URL that ends with a trailing slash when the request is for a directory. This is very important because it prevents the contents of the directory from being listed even if you have an index file (e.g. index.html). The DirectorySlash directive's documentation says:
Security Warning
Turning off the trailing slash redirect may result in an information disclosure. Consider a situation where mod_autoindex is active (Options +Indexes) and DirectoryIndex is set to a valid resource (say, index.html) and there's no other special handler defined for that URL. In this case a request with a trailing slash would show the index.html file. But a request without trailing slash would list the directory contents.
That means, if you want to be able to go to directories without the trailing slash, you need to turn off DirectorySlash, and that means people will be able to see the contents of your directories (or get a 403 if you have Indexes turned off). So the only way around this is to do what DirectorySlash does except using mod_rewrite:
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*[^/])$ /$1/ [L]
edit: you've got other issues with your existing rules, try:
DirectorySlash Off
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*[^/])$ /$1/ [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/$1.html -f
RewriteRule ^([^\.]+)/?$ $1.html [NC,L]

htaccess rewrite rules to remove multiple subfolders from a URL

Due file system sub-directory constraints I will most likely reach I want to separate the /users folder into /users/a/username, /users/b/username, /users/c/username, etc.
So the data on the server for a user would be in:
www.domain.com/users/a/username/, www.domain.com/users/b/username/, etc
I want the URL to be:
www.domain.com/users/username/
Optionally to avoid duplicate content a 301 redirect from www.domain.com/users/a/username/ to www.domain.com/users/username/ would also be good.
Currently I have a rewrite for a single sub-directory (see below) but I'm confused how this can be done efficiently for all of the alphabetical sub-directories.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^users/(.*)$ users/a/$1 [L,NC]
I have checked this site and all seem to hide the first sub-directory e.g. domain.com/folder1/filename.html => domain.com/filename.html but nothing in more depth.
Put this code in your htaccess (which has to be in root folder)
Options -Indexes -MultiViews
RewriteMap lowercase int:tolower # this line in your apache file configuration
RewriteEngine On
RewriteCond %{THE_REQUEST} \s/users/[a-z]/([^/\s]+)\s
RewriteRule . /users/%1/? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^users/([A-Za-z])([^/]+)/$ /users/${lowercase:$1}/$1$2/ [L]

Serve resource files bypassing a framework using .htaccess directives

I'm using the Kohana framework. It has the following configuration of .htaccess file:
# Protect application and system files from being viewed
RewriteRule ^(?:application|modules|system)\b.* index.php/$0 [L]
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite all other URLs to index.php/URL
RewriteRule .* index.php [PT]
I'm particulary interested in the second part Allow any files or directories that exist to be displayed directly. Can someone please elaborate in details on how it's configured?
It is due to 2 condition lines using RewriteCond directive that acts like if condition
RewriteCond %{REQUEST_FILENAME} !-f
Means if request is NOT for a valid file
RewriteCond %{REQUEST_FILENAME} !-d
Means if request is NOT for a valid directory
Both combined with RewriteRule below mean that if request is not a valid file or directory then forward every request to index.php

Apache mod_rewrite never rewrite for existing directory except directory is certain directory?

A website http://www.example.com/ runs on a CMS and everything goes through it by rules set in .htaccess. When visiting http://www.example.com/ the user is redirected to one of the following paths depending on the user's language settings:
http://www.example.com/en/
http://www.example.com/fr/
The /en/ and /fr/ directories don't really exist, they are processed by the CMS.
I am adding a new section (investors/) to the site but don't want it to go through the CMS for now, but I don't want the users to notice it.
The original .htaccess file has these lines:
# never rewrite for existing files, directories and links
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
# rewrite everything else to index.php
RewriteRule .* index.php [L]
I managed to make it not go through the CMS if the requested path begins with /en/investors/ or /fr/investors/:
# never rewrite for existing files, directories and links
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
# rewrite everything else to index.php
# except investors' section
RewriteRule ^(?!\/en\/investors|\/fr\/investors).+ index.php [L]
I uploaded my /en/investors/ and /fr/investors/ directories onto the server and they work fine, but now the home page is broken because the /en/ and /fr/ directories now exist. How can I add exceptions to that rule?
Simple add another rule to cover the 2 directories e.g.
RewriteRule ^(en|fr)/?$ index.php [L]