Include two document roots in Apache? - apache

I have http://example.com/pic1.jpg, pic2.jpg, pic3.jpg, and so on for hundreds of jpgs, on my original server, but I need to move it to http://example.com/pictures/pic[##].jpg. Many different servers and pages link to these pictures, so if at all possible, I don't want to just move the pictures and change the links. Is it possible to include another directory as a second document root in Apache?
So, even though the picture is actually located at /pictures/pic1.jpg, linking to just /pic1.jpg will work fine too?
Edit: I don't want to symlink because of the clutter from having so many pictures in the root.

You can use a .htaccess file in root directory to redirect all requests to pictures directory when there is no file in root with that name.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /pictures/$1 [L]
An about main question. No it is not possible to have two document root (Not acceptable from logical point of view too). But you can redirect requests using .htaccess file.

In my httpd.conf file, for the document root, I have the following block now:
<Directory />
Options FollowSymLinks
AllowOverride None
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+) http://example.com/pictures%{REQUEST_URI}
</Directory>
So, if you try to go to http://example.com/pic1.jpg and it doesn't exist, it will then redirect you to http://example.com/pictures/pic1.jpg. This could be made better, like only doing it when REQUEST_URL contains .jpg, but it works for me for now.

Related

How to change the first segment of a URL and maintain the rest of the segments in htaccess

I have pages in my site where the url segment are automatically filled depending on the values of the fields in the page.
And example url is:
http://example.com/students/uk/nikki/86/18-25
where nikki/86/18-25 are dynamic segments.
What I was to do is to simple make an htaccess redirect rule where if a user will go to:
http://example.com/students/uk/nikki/86/18-25
they will automatically be redirected to:
http://example.com/student/uk/nikki/86/18-25
So it's just to make the students segment to student. And since the nikki/86/18-25 segments changes per page, they would be retained during the redirect.
Is this possible in htaccess?
Try adding this to the .htaccess file in your web document root folder (often public_html or htdocs):
Options -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^students/uk/([^/]+) student/uk/$1 [L,R,DPI]
Once you are satisfied that the redirect works, you can change the R to R=301 to make it permanent.
This assumes that mod_rewrite is both installed and activated for htaccess files.
If you are not sure, to check if mod_rewrite is installed, look at the list of installed modules in the output of phpinfo();
By default, mod_rewrite is not enabled for htaccess files. If you are managing your own server, open httpd.conf
and make sure that the webroot directory block contains one of these lines: AllowOverride FileInfo or AllowOverride All

Redirect all to index.php using htaccess

I am writing a simple PHP-based MVC-ish framework. I want this framework to be able to be installed in any directory.
My PHP script grabs the request uri and breaks it off into segments. It makes segment 1 the controller and segment 2 the action. This goes all fine when I do this:
http://www.example.com/mvc/module/test/
It will go to the specific module controller and method. Now I have a default controller, the home controller, which is in folder home.
Now when I access this folder directly http://www.example.com/mvc/home/
It will display a 403 forbidden , because this folder does exist, instead it should also go back to http://www.example.com/mvc/index.php
If I would have installed the framework in a different folder, lets say folder framework it has to redirect back to http://www.example.com/framework/index.php
I would like to redirect every folder and php file back to the index.php, leaving everything else the way it is.
My first problem I encountered was it never redirects to the right folder, always to the domain root folder.
This is what I tried :
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
Your rewrite rule looks almost ok.
First make sure that your .htaccess file is in your document root (the same place as index.php) or it'll only affect the sub-folder it's in (and any sub-folders within that - recursively).
Next make a slight change to your rule so it looks something like:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?path=$1 [NC,L,QSA]
At the moment you're just matching on . which is one instance of any character, you need at least .* to match any number of instances of any character.
The $_GET['path'] variable will contain the fake directory structure, so /mvc/module/test for instance, which you can then use in index.php to determine the Controller and actions you want to perform.
If you want the whole shebang installed in a sub-directory, such as /mvc/ or /framework/ the least complicated way to do it is to change the rewrite rule slightly to take that into account.
RewriteRule ^(.*)$ /mvc/index.php?path=$1 [NC,L,QSA]
And ensure that your index.php is in that folder whilst the .htaccess file is in the document root.
Alternative to $_GET['path'] (updated Feb '18 and Jan '19)
It's not actually necessary (nor even common now) to set the path as a $_GET variable, many frameworks will rely on $_SERVER['REQUEST_URI'] to retrieve the same information - normally to determine which Controller to use - but the principle is exactly the same.
This does simplify the RewriteRule slightly as you don't need to create the path parameter (which means the OP's original RewriteRule will now work):
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [L,QSA]
However, the rule about installing in a sub-directory still applies, e.g.
RewriteRule ^.*$ /mvc/index.php [L,QSA]
The flags:
NC = No Case (not case sensitive, not really necessary since there are no characters in the pattern)
L = Last (it'll stop rewriting at after this Rewrite so make sure it's the last thing in your list of rewrites)
QSA = Query String Append, just in case you've got something like ?like=penguins on the end which you want to keep and pass to index.php.
To redirect everything that doesnt exist to index.php , you can also use the FallBackResource directive
FallbackResource /index.php
It works same as the ErrorDocument , when you request a non-existent path or file on the server, the directive silently forwords the request to index.php .
If you want to redirect everything (including existant files or folders ) to index.php , you can use something like the following :
RewriteEngine on
RewriteRule ^((?!index\.php).+)$ /index.php [L]
Note the pattern ^((?!index\.php).+)$ matches any uri except index.php we have excluded the destination path to prevent infinite looping error.
There is one "trick" for this problem that fits all scenarios, a so obvious solution that you will have to try it to believe it actually works... :)
Here it is...
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,QSA]
</IfModule>
Basically, you are asking MOD_REWRITE to forward to index.php the URI request always when a file exists AND always when the requested file doesn't exist!
When investigating the source code of MOD-REWRITE to understand how it works I realized that all its checks always happen after the verification if the referenced file exists or not. Only then the RegEx are processed. Even when your URI points to a folder, Apache will enforce the check for the index files listed in its configuration file.
Based on that simple discovery, turned obvious a simple file validation would be enough for all possible calls, as far as we double-tap the file presence check and route both results to the same end-point, covering 100% of the possibilities.
IMPORTANT: Notice there is no "/" in index.php. By default, MOD_REWRITE will use the folder it is set as "base folder" for the forwarding. The beauty of it is that it doesn't necessarily need to be the "root folder" of the site, allowing this solution work for localhost/ and/or any subfolder you apply it.
Ultimately, some other solutions I tested before (the ones that appeared to be working fine) broke the PHP ability to "require" a file via its relative path, which is a bummer. Be careful.
Some people may say this is an inelegant solution. It may be, actually, but as far as tests, in several scenarios, several servers, several different Apache versions, etc., this solution worked 100% on all cases!
You can use something like this:
RewriteEngine on
RewriteRule ^.+$ /index.php [L]
This will redirect every query to the root directory's index.php. Note that it will also redirect queries for files that exist, such as images, javascript files or style sheets.
Silly answer but if you can't figure out why its not redirecting check that the following is enabled for the web folder ..
AllowOverride All
This will enable you to run htaccess which must be running! (there are alternatives but not on will cause problems https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride)
just in case you were still wondering how to redirect all request either if the directory exists (for core framework folders and files) to the framework index handler, after some error/success attempts just noticed I just needed to change the RewriteCond in the .htaccess file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
the above condition states "not found files" and "not found directories", ok, what if just remove "not found" (!-d) line, and ended with something like the below:
RewriteEngine on
RewriteBase /framework/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /framework/index.php [L,QSA]
It worked for me like a charm
I just had to face the same kind of issue with my Laravel 7 project, in Debian 10 shared hosting. I have to add RewriteBase / to my .htaccess within /public/ directory. So the .htaccess looks a like
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [L,QSA]
After doing that don't forget to change your href in,
home
Example:
.htaccess file
RewriteEngine On
RewriteRule ^about/$ /about.php
PHP file:
about

.htaccess Rewrite for PDFs from root to subdirectory

I'm trying to automatically redirect all .PDF and .pdf files from the website root to a subdirectory called docs.
Note that there aren't any actual PDFs on the website root, which is why I'm trying to use the !-f bit.
This is what I came up with so far, but it isn't working. I would appreciate any help.
# redirect PDF files requested on the root '/' to /docs/<filename>.(pdf|PDF)
Options +SymLinksIfOwnerMatch
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.(pdf|PDF))$ /docs/$1
Try changing your rule to:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/docs%{REQUEST_URI} -f
RewriteRule ^/?(.*\.pdf)$ /docs/$1 [L,NC]
The second condition may not be needed, it's there in case a request is made that ends with ".pdf" but the pdf isn't actually there, thus the first condition is true and there's a rewrite loop (resulting in a 500 server error).

HtAccess Rewrite Can't Find File

I have a small web app that I'm in the process of deploying to a server. However, suddenly the htaccess file isn't working (not the index file, but when I go to a url such as /login). It keeps maintaining that the file doesn't exist, however, the file that it displays as "unfindable" definitely does exist. I checked the relative path /home/sites/xxx.co.uk/public_html/index.php displayed by the error with a file_get_contents and it shows the file.
DirectoryIndex index.php
Options -Indexes
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*[^/])/?$ index.php?route=$1 [L,QSA]
Does anyone know what is happening?
Sorted it, it was just something with my Hosting Provider. The site was being tested on a test url they provided (while the domain is registered) and they had a strange method of identifying your folder (needed /home/sites to be removed)

Apache ignoring file extensions

I use the following .htaccess code to make my URLs cleaner:
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [L]
It basically check if the requested URL points to a file or a directory and if it doesn't, it formats it in a particular way.
The problem is that my production server seems to ignore file extensions when it checks if the requested URL points to a file. For example, it would consider the URL /contact pointing to a file named contact.jpg if a file with that name existed on the root of the server.
What causes Apache to behave like that and what can I do to control it - make it strict about file extensions?
I believe it's because of MultiViews option.
Try Options -MultiViews in the .htaccess