Redirect to a single file in apache - php

I have an index.php file in the DocumentRoot of a virtualHost in apache. It contains :
$path = $_SERVER['REQUEST_URI']
if($path == '/')
echo json_encode(some_data);
else if ($path == '/posts')
echo json_encode(another_data);
the thing is when I send a get request to / it respond with the data I wanted, but when requesting /posts or any endpoint other than /, the server respond with not found page.
How can I make it use index.php for every request that virtualhost ?
I want all the requests to be handled by index.php

WordPress deals with that by adding this to the .htaccess file:
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
Basically, you need to redirect all requests to index.php, but not using a 301 or 302, just rewriting. The RewriteCond lines are to make it so users can still access other files directly if they exist. You may not need those in your implementation.
Here's an explanation of the code:
RewriteEngine On turns on the rewrite engine :)
RewriteBase / Just makes sure we're starting from the document root
RewriteRule ^index\.php$ - [L] is a rule that does nothing if the request is for index.php. the [L] means no more rules will be processed.
The two RewriteCond lines make sure that there's not a matching file (1st line) or directory (2nd line) for the request. If there is, then the following RewriteRule won't take effect, and the server will serve up that file or directory. Otherwise:
RewriteRule ^index\.php$ - [L] will rewrite the request to /index.php, making your script handle the request without redirecting the user's browser to index.php.
If there is no .htaccess file, you'll need to add one, or add the rules to the conf file for this virtualhost. The conf file will also need to allow overrides to see the .htaccess file:
<Directory "/path/to/document/root">
AllowOverride All
</Directory>

You can use FallbackResource:
FallbackResource /index.php
Set it in your virtual host settings or in an .htaccess file.

Related

Apache uses it's own 404 handler instead of index.php for .txt files

I want to serve all requests for non-existing files via .php
.htaccess configuration:
ErrorDocument 404 /index.php
DirectoryIndex index.php
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
This does seem to mostly work but some specific file extensions (.txt,.jpg, some more?) get handled by apache instead of getting passed through php.
http://localhost:8000/home -> shows homepage
http://localhost:8000/file.zip (does not exist) -> shows custom styled 404 page served by PHP
http://localhost:8000/exists.txt (existing file) -> serves existing file
http://localhost:8000/doesnotexist.txt (does not exist) -> shows default apache 404 page (same as when no PHP is installed)
Is there some default apache handler for specific file extensions?
How can I set ALL requests to get passed through index.php?
Using docker php 7.4 apache as my base image
I copied your experiment with Docker and the php 7.4-apache image. When opening the url http://localhost:8000/doesnotexist.txt I'm transfered to the index.php file as I would expect to be. The bottom three rewrite rules will rewrite everything to index.php.
First off: You have not posted a docker-compose.yml or Dockerfile, so to be sure: you have to enable the rewriting for Apache by either a command in the dockerfile or a custom Dockerfile like this:
# Dockerfile
FROM php:7.4-apache
RUN a2enmod rewrite
If you would not have enabled the rewrite, an error 500 should appear, because there are no if-conditions around the rewrite rule.
If you did enable the rewriting, the behaviour is still strange, because even if the line ErrorDocument 404 /index.php is not there the bottom rewrite should make that the index.php is served anyway. In other words: The bottom three lines in the .htaccess would make sure that no 404 is served, because everything is rewritten to the index.php.
When you say 'the default apache 404 page' are you talking about the 'Not found' page?
Not Found (H1 tag)
The requested URL was not found on this server.
Apache/2.4.52 (Debian) Server at localhost Port 8000
Try to remove and rebuild the container, so that no weird caching issue can give problems.
And what about your index.php. Is there anything in there that could trigger something strange? Could you post it here?
Try this in your .htaccess file (without the ErrorDocument part):
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php?file=$0 [QSA,L]
Make sure you output 404 if the code does'nt find the file.
Is there some default apache handler for specific file extensions?
No, there is not such a handler by default.
How can I set ALL requests to get passed through index.php?
ErrorDocument 404 /index.php is valid.
DirectoryIndex index.php is valid
RewriteEngine on is valid
RewriteCond %{REQUEST_FILENAME} !-f is valid
RewriteCond %{REQUEST_FILENAME} !-d is valid
RewriteRule ^ index.php [L] is also valid!
Keep in mind that you are not rewriting it to the root /index.php, instead you are rewriting without the slash, and it rewrites to the index.php in the current directory. So if index.php doesn't exist in the current directory, chances it can get into an infinite loop.
Try:
ErrorDocument /index.php
DirectoryIndex index.php
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L] # use '/index.php' if needed to redirect to root index.php
This will redirect that everything exists to index.php, and avoid conflicts with ErrorDocument.
But, I think this actually what you mean to do:
ErrorDocument /index.php
DirectoryIndex index.php
# remove those rewrite rules

How can I get mod_rewrite to rewrite everything?

What I've been trying to achieve is to get my .htaccess file to rewrite ALL URLS.
No matter what I do, however, I cannot get it ignore existing directories. And by that, I mean, act as if they don't exist.
For example, say I have the following file structure:
/
dir1
file1.php
dir2
file2.php
.htaccess
And suppose I want to redirect all traffic to dir1/file1.php?url=path.
This never works for me if the path is an existing directory.
For example, if I navigate to url/path/stuff/dir2, the "redirecting" works, but the URL in the address bar changes to url/path/stuff/dir2/?url=dir2 for some unfathomable reason.
Here is my .htaccess:
Options -MultiViews
Options -Indexes
Options +FollowSymLinks
# so navigating to a url with a trailing slash won't cause problems
DirectorySlash Off
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dir1/file1.php?url=$1 [QSA,L]
You (updated) .htaccess is saying: IF (it is not an existing file) THEN { rewrite the URL }. Seems like you want
RewriteEngine on
RewriteCond %{REQUEST_URI} !dir1/file1.php
RewriteRule ^(.*)$ dir1/file1.php?url=$1 [QSA,L]
In this case, the RewriteCond just prevents infinite looping. The RewriteRule gets applied once and only once. Rewrite module will keep cycling thru all the rules until a cycle does not result in a changed to the URI.

mod_rewrite - check for existing files and directories

I have 2 domain names, foo.com and bar.com and a .htaccess file at the root of bar.com asking all requests to bar.com to redirect to foo.com except the initial search for a directory index file, which gets pointed to a specific php file (functions.php) at foo.com.
This means that a request for bar.com or www.bar.com will see foo.com/functions.php accessed and the various requests for images, stylesheets etc. continue to access the rewritten relative path of foo.com/images/image.jpg rather than foo.com/function.phpimages/image.jpg. This all works fine.
Now, the problem.
I want to include a subdirectory on bar.com that doesn't redirect. As in, a request for bar.com/newdirectory/ goes to that directory and all relative file requests behave as normal while keeping the original rule (described above) for anyone accessing bar.com at root. Currently I get a 404 if I try and access the new subdirectory.
In my original .htaccess file I had included a loose code for checking that files do not exist. I tried adding the flag !-d to check if directories don't exist first but this has resulted in requests to bar.com going straight to foo.com rather than foo.com/functions.php
Current .htaccess file:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
# Check the request isn't an existing file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^$ http://www.foo.com/functions.php [P]
RewriteCond %{REQUEST_FILENAME} !^$ [NC]
RewriteRule ^(.*) http://www.foo.com/$1 [P]
You can add after RewriteBase / :
RewriteRule ^newdirectory/? - [L]
And for others. No need to test file, because you redirect empty URI only.
You can use :
RewriteRule ^$ http://www.foo.com/functions.php [P]
RewriteRule ^(.+) http://www.foo.com/$1 [P]
Which gives for all .htaccess:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule ^newdirectory/? - [L]
RewriteRule ^$ http://www.foo.com/functions.php [P]
RewriteRule ^(.+) http://www.foo.com/$1 [P]

How to add content HTTP_HOST variable to query string

i need to create a rewrite rule/condition that always rewrites the http_host to the query string.
i have multiple domains and all of them point to the same DocumentRoot.
What i want to do now is, to add the called domain-name (e.g.) example1.org to the query-string for application internal use. Let's say the application is situated at baseapplication.org
opening
example.org
in my browser runs into document root and htaccess should rewrite it internally to:
baseapplication.org?requested_domain=example1.org
i cannot find a combination of rewrite rules or conditions to get that running.
Im not a .HTACCESS pro, but this should do the trick.
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
have that in your root, in a file named .HTACCESS along with a index.php file.
Then in the index file you can access all the request vars.
From here you can either do a php headers redirect, or include the file from another dir.
up to you.
Not a solution, but should help a little
From the Apache documentation:
Description:
Assume that you want to provide www.username.host.domain.com for the homepage of username via just DNS A records to the same machine and without any virtualhosts on this machine.
Solution:
For HTTP/1.0 requests there is no solution, but for HTTP/1.1 requests which contain a Host: HTTP header we can use the following ruleset to rewrite http://www.username.host.com/anypath internally to /home/username/anypath:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.[^.]+\.host\.com$
RewriteRule ^(.+) %{HTTP_HOST}$1 [C]
RewriteRule ^www\.([^.]+)\.host\.com(.*) /home/$1$2
There are a handful of other HTTP rewrites at the Apache Rewrite Guide.

Simple problem with mod_rewrite in the Fat Free Framework

I am trying to setup and learn the Fat Free Framework for PHP.
http://fatfree.sourceforge.net/
It's is fairly simple to setup and I am running it on my machine using MAMP.
I was able to get the 'hello world' example running just fin:
require_once 'path/to/F3.php';
F3::route('GET /','home');
function home() {
echo 'Hello, world!';
}
F3::run();
But when I try to add in the second part, which has two routes:
require_once 'F3/F3.php';
F3::route('GET /','home');
function home() {
echo 'Hello, world!';
}
F3::route('GET /about','about');
function about()
{
echo 'About Us.';
}
F3::run();
I get a 404 error if I try the second URL: /about
Not sure why one of the mod_rewrite commands would be working and not the other.
Below is my .htaccess file:
# Enable rewrite engine and route requests to framework
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L,QSA]
# Disable ETags
Header Unset ETag
FileETag none
# Default expires header if none specified (stay in browser cache for 7 days)
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault A604800
</IfModule>
So my friend actually helped me out with this issue. I ran into the exact same problem, but basically I'm using MAMP also and have all my Fat Free files within a fatfree dir within htdocs of MAMP.
The solution is you need to mod the RewriteBase to point to /[dirname]/ instead of just / and then change RewriteRule to /[dirname]/index.php.
My .htaccess looks like this:
RewriteEngine On
RewriteBase /fatfree/
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /fatfree/index.php [L,QSA]
After that's set, you can follow the example in the Fat Free doc exactly and it'll work like a charm. This stumped me for a while and this was all it needed. Also, if you're using MAMP, edit the httpd.conf file in /Applications/MAMP/conf/apache and be sure to alter the following:
<Directory />
Options Indexes FollowSymLinks
AllowOverride None
</Directory>
to
<Directory />
Options Indexes FollowSymLinks
AllowOverride All
</Directory>
Basically change None to All.
If you're running F3 under a subfolder, you must change the RewriteBase in .htaccess to match the folder.
In your .htaccess you have 'index.php' it needs a slash ... '/index.php'
# Enable rewrite engine and route requests to framework
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /index.php [L,QSA]
otherwise when it tries to rewrite /about/ it will look for /about/index.php instead of just the root /index.php
I just had another thought.. it 'is' possible that althought mod_rewrite is intalled there may be a quirk with the server causing it not to rewrite..
If the global route below doesnt work you might want to test the rewrite
RewriteRule ^/google http://www.google.com [L,NC];
You could also try a global route for the directory
F3::route('GET /about/*','about');
but that means anythin under domain.com/about/ ...... anything ... will reroute to the about function...
A note about mod_rewrite and FF
As you said, FF is givikng you a 404 because it is expecting '/' instead of '/index.php'... However, it is the index.php which is expecting the difference..
To demonstrate that, i believe you can duplicate your
F3::route('GET /','home');
as
F3::route('GET /index.php','home');
and the page should display...
The reason for this is if you just go to the / directory (or /index.php) eitehr way apache servesx the index.php page....
The mod_rewrite allows you to redirect the /about and have it redirect to the index.php.. So if your rewrite rule is not working then the redirect/rewrite does not happen and you will get a 404...
As i mentioned above, test the mod_rewrite with the google rule.. then try to go to http://localhost:80/google
if it does not redirect you to google then your rewrite engine is not working... (probably an issue with the windows configuration..)
to enable mod_rewrite under windows:
Open your http.conf
Find this line:
#LoadModule rewrite_module modules/mod_rewrite.so
remove the comment mark (#) from the line... so you have:
LoadModule rewrite_module modules/mod_rewrite.so
Save the file and restart apache..
Alternatly.. I think you can just say:
LoadModule rewrite_module modules/mod_rewrite.so
at the start of your htaccess file...
I banged my head on this for 2 days. I debugged htaccess and php both. The actual problem is this :
If you copied the .htaccess file from their fatfree-1.4.4 zip download, its not .htaccess its htaccess (. is missing) Just rename this file to .htaccess from htaccess and everything will work perfectly as its mentioned in the document !!!
I am using this .htaccess works for non-root folders too
Options -Indexes
IndexIgnore *
RewriteEngine On
RewriteCond $1 !^(index\.php|images|main\.css|form\.css|favicon\.ico|robots\.txt|sitemap\.xml)
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
Note: If you want to call your .htaccess file something else, you can change the name of the file using the AccessFileName directive. For example, if you would rather call the file .config then you can put the following in your server configuration file:
AccessFileName .config
here
This response may be too late for you but I had the same problem yesterday.
It sounds like the problem is apache is not rewriting urls. I had the same issue when trying to get F3 running on OSX 10.7 - the 'GET /' route would work but not the 'GET /foo' as the F3 index.php was in a subdir for localhost/F3. My solution was to:
ensure the .htaccess was set as you have.
ensure mod_rewrite.so was enabled in apache's httpd.conf
ensure that you set AllowOverride All (mine was None) for your web directory in httpd.conf (further down the file).
restart apache
Without step 3, apache will ignore any rewrite directives. I discovered this by changing the permalinks on a local wordpress install and they failed indicating the problem was the apache config, not F3.
I'm running this with a MAMP stack.
I renamed their folder from "fatfree-master" to "f3".
I put that folder next to htdocs.
Their .htaccess file (now inside MAMP/f3/lib) remains untouched.
My .htaccess (in my web subfolder) is stock standard as per their example:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule .* index.php [L,QSA]
Hope this helps someone.
I had the same issue and i solved it by moving the .htaccess file to the root directory of the fatfree project.
create a file .htaccess with folowing code at root directory
# Enable rewrite engine and route requests to framework
RewriteEngine On
# Some servers require you to specify the `RewriteBase` directive
# In such cases, it should be the path (relative to the document root)
# containing this .htaccess file
#
# RewriteBase /
RewriteCond %{REQUEST_URI} \.ini$
RewriteRule \.ini$ - [R=404]
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L,QSA]
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]

Categories