htaccess rewrite - 404 on existing file - apache

So I have the following rewrite in an htaccess file:
RewriteRule ^([^/.]+)/?$ index.php?page=$1 [L]
Whenever I try to go to http://domain/index I get a 404, but when I try to go to http://domain/index. or even a non-existent page like http://domain/a, the rewrite works just fine and index.php var_dump()s the appropriate values.
The only code in index.php is var_dump($_GET);, so I know it's not a php issue.
Can someone explain to me what's wrong with my rewrite rule, and explain how to fix it?
EDIT:
I forgot I had error logging enabled. The error it keeps saving to error.log is:
[Sun Feb 24 21:01:18 2013] [error] [client 192.168.1.1] Negotiation: discovered file(s) matching request: /path/public_html/index (None could be negotiated).

By the error, it seems MultiViews is enabled.
You may try this at the top of the file:
Options +FollowSymlinks -MultiViews
Additionally, I suggest the following:
# Prevent loops
RewriteCond %{REQUEST_URI} !index\.php [NC]
RewriteRule ^([^/]+)/? index.php?page=$1 [L]
MultiViews provides for Content Negotiation, best described here

When MultiViews is enabled (Options +MultiViews), the Content Negotiation module looks for files that match index, but .php files don't qualify for a match, so it fails with None could be negotiated. You can add .php handlers as matches using:
MultiviewsMatch Handlers Filters
as documented in MultiviewsMatch.

Related

RewriteRule with query string gets rewritten to /param/param/

I have this rewriterule:
RewriteRule ^gallery/([^/]+)/?$ /gallery.php?title=$1 [L]
However, when navigating to gallery/a/, the internal redirect is to :
gallery.php/a //(instead of: gallery.php?title=a)
What would cause this behavior?
Option MultiViews might be culprit here. Option MultiViews is used by Apache's content negotiation module that runs before mod_rewrite and and makes Apache server match extensions of files. So /file can be in URL but it will serve /file.php.
Turn it off by using this line at top of your .htaccess:
Options -MultiViews

Rewriterule alias matching directory name?

Is it possible to create a rule that matches an existing directory?
As in the following example:
RewriteRule ^foo$ foo.php
Considering that is also a folder called "foo", Apache tries to open the directory instead of parsing the rule. Is it possible that the rule precedes the directory?
thank you
Testing with the following config:
Options +FollowSymlinks
Options -MultiViews
RewriteEngine on
AddDefaultCharset iso-8859-1
RewriteRule ^foo$ foo.php
And receiving the following error from apache: [Fri Mar 07 15:06:34 2014] [alert] [client 127.0.0.1] C:/htdocs/www.acasa.org.br.v2/.htaccess: Option MultiViews not allowed here
You need to use -MultiViews for it to ignore the folder.
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteRule ^foo/?$ foo.php [L]
You can toggle DirectorySlash on and off with:
DirectorySlash Off
However the suggested way to resolve your images issue is by using:
<base href="http://www.domain.com/" />

RewriteCond: unknown flag 'QSA'

When configuring Restler it suggests creating the following re-write rule:
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^$ index.php [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>
I have put this into a .htaccess file in root of my REST directory but I'm getting a 500 Server error when this rule is being fired. The error message the apache error log is:
[Wed Oct 10 10:39:30 2012] [alert] [client 127.0.0.1] /public/api/.htaccess: RewriteCond: unknown flag 'QSA'
[Wed Oct 10 10:39:30 2012] [error] [client 127.0.0.1] File does not exist: /public/favicon.ico
I assume the lack of a favicon.ico file can be ignored but I am concerned about the "unknown flag 'QSA'" error. I know very little about rewrite rules so any help there would be appreciated.
For those familiar with Restler, I am using 3.0.0rc2 (if that matters). Also it's worth pointing out that using the explicit call to index.php works so much as I then get a 404 JSON error response (a positive improvement) but as indicated above if I rely on the rewrite rule then I just get a 500 Server Error:
http://localhost/api/index.php/say/hi - WORKS (gives JSON 404 error)
http://locahost/api/say/hi - 500 SERVER ERROR
It doesn't look like the error has anything to do with the rules that you have:
/public/api/.htaccess: RewriteCond: unknown flag 'QSA'
which says that the QSA flag is an unknown flag for a RewriteCond, followed by a favicon.ico not found so I'm guessing that it's unrelated to requests into your REST directory.
If you had AllowOverride None, then your htaccess file is simply going to be outright ignored. There are different aspects of configuration options that can be overridden inside htaccess files, None means, htaccess cannot override any configurations, so it'll just get ignored.
The QSA flag isn't needed at all here. You only need it when you are rewritting the query string and want to append the original query string to the end. By default, the query string is appended anyways.
Interesting ... I was looking into my JSON 404 message and found this post:
Restler always returns not found
It not only solved my 404 error but also helped to fixed the 500 Server error. The only thing I needed to do was change the http.conf's AllowOverride to All.
I'd still be interested if anyone could tell me WHY this is happening but the this does now work.

Apache htaccess file, where did I go wrong?

Really can't find my mistake, I can access the sitemap/ link, but all the others give a 404 Not Found Error.
DirectoryIndex index.php index.php?page=home index.php?page=error
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
Allow from all
<IfModule mod_rewrite.c>
RewriteEngine On
# some other stuff #
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteBase /
RewriteRule ^sitemap/?$ sitemap.xml.php [L]
RewriteRule ^([a-zA-Z]+)/?$ index.php?page=$1 [L]
RewriteRule ^products/?$ index.php?page=products [L]
RewriteRule ^products/([0-9]+)/?$ index.php?page=products&id=$1 [L]
</IfModule>
I'd really appreciate some help, I definitely suck at .htaccess files...
Rewriting rules aside, you have other problems here:
DirectoryIndex index.php index.php?page=home index.php?page=error
This means, that, for a folder a file showing index will be selected in this order (first one existing wins):
index.php
index.php?page=home (this is the filename)
index.php?page=error (this is the filename)
I doubt this was your intention.
Next:
AllowOverride All
If you're already in .htaccess and AllowOverride was restrictive, this will not help, and if it wasn't, then there is no point of writing this again.
Order allow,deny
Allow from all
This basically says "allow everyone everywhere" which is the default anyway. Unless it was restricted in some way on upper level or in apache configuration, this is redundant.
As for rewrite:
RewriteRule ^([a-zA-Z]+)/?$ index.php?page=$1 [L]
RewriteRule ^products/?$ index.php?page=products [L]
The second rule is redundant anyway, and will never be reached (as the first one matches it as well).
As for the error you're seeing:
[Wed Jul 04 02:56:30 2012] [error] [client 127.0.0.1] File does not exist: /var/www/home"
This may mean problems with DocumentRoot definitions. Please, post your VirtualHosts configuration.

How can I have rewrite rules with aliases?

I apologize in advance if this is too long. I figure more detail is better than less and hope I'm not being horribly rambling :-)
I use WAMP on my laptop for local dev, and I have various c:/wamp/alias/* files each pointing to a project working directory. I've had some excellent mod_rewrite help and gotten
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*\/)?ih(\/.*)?$ $1index.php$2 [L,QSA]
to work to change localhost/.../ih/sub/dir to localhost/.../index.php/sub/dir for URLs that are both SEO-friendly and short. [I haven't gone on to do this in prod but I suspect it will work just as well.] However, to get it all together I had to change my doc root from c:/wamp/www/ to c:/, which I'd really rather not do just in case my Apache gets hacked and otherwise because it's a kludge.
My test alias file looks like
Alias /testme "c:/var/tmp/wamp-testme/"
<Directory "c:/var/tmp/wamp-testme/">
Options Indexes FollowSymLinks MultiViews
AllowOverride all
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*\/)?ih(\/.*)?$ $1index.php$2 [L,QSA]
</Directory>
and the error I get when trying to load http://localhost/testme/rewrites/ih/sub/path is
[Thu Jun 30 06:46:13 2011] [error] [client 127.0.0.1]
File does not exist: C:/wamp/www/var
with a matching
Not Found
The requested URL /var/tmp/wamp-testme/rewrites/index.php/sub/path
was not found on this server.
in the browser. Sure enough, the same config in my c:/wamp/alias/flying.conf file that points to the c:/data/flying/ directory throws File does not exist: C:/wamp/www/data in the error log file, and so on.
Sooooo... How can I have a rewrite rule that transcends aliases without having my doc root at my machine root dir?
Odd: try adding a PT flag to the rewrite rule: this forces the re-written URL to be sent back to the URL mapping engine.
EDIT: try setting the RewriteBase on the Directory.