htaccess shows "Not Found" if directory does not exist - apache

I want rewrite everything that matches <domain>/something/mypage.htm to something.php?pid=mypage, so I wrote the following .htaccess file:
RewriteEngine On
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+).htm$ $1.php?pid=$2
DirectoryIndex home.php
On my old webhosting provider, the rules worked as expected, but on the new provider, it says "Not Found" when I try to open <domain>/something/index.htm or similar. But when I create a directory called something, the rewrite rule works as expected.
Is anyone having any idea what's wrong here?

It looks like MultiViews is perhaps enabled on the new server and this will conflict with your mod_rewrite directive.
With MultiViews enabled and you request /something/mypage.htm (when /something.php exists as a physical file), mod_negotiation will issue a subrequest for /something.php/mypage.htm (that's /something.php with path-info of /mypage.htm) before your mod_rewrite directive is able to process the request, so no pid parameter is passed. (Your directive does not match a dot in the first path segment, so the subrequest by MultiViews does not match.)
The 404 will result from either Apache, if AcceptPathInfo Off is set (perhaps in the server config), or from your script because the pid parameter is not being passed.
When you create a subdirectory called something, MultiViews does not rewrite the request since it already matches something, ie. the directory by that name.
You need to ensure that MultiViews is disabled at the top of your .htaccess file:
Options -MultiViews
NB: MultiViews is not enabled by default on Apache, but some shared webhosts do enable it for some reason. It makes extensionless URLs "magically" work out of the box, but actually causes many more problems if you are not expecting it.

Related

mod_rewrite doesnt work if file with same name as argument exists

I'm experiencing some issues with mod_rewrite in htaccess.
Let's for instance say I request example.com/foo/, it works perfectly if I don't have a file starting with "foo.*" in the root directory.
Let's say I have news.php, sitemape.xml, style.css in root, I can't use /news/ or /sitemap/ or /style/ , it will give a 404 like /news.php/ etc.
Here's my rewrite string. It works locally with my Apache 2.2.22 but not at my web-host with the same Apache version.
RewriteRule ^([A-Za-z0-9]+)/?$ index.php?category=$1 [NC,L]
Anyone has a clue?
This sounds like Multiviews rearing its ugly head when its not wanted. It may be that your host automatically turns on the Multiviews option by default, and mod_negotiation then tries to "guess" what the request is for, and if it's close enough (like with /news/ and /news.php), it will automatically serve it, and disregard whatever mod_rewrite rules you may have.
Try turning off multiviews. You can do this in your htaccess file using the Options directive (assuming your host has allowed Options):
Options -Multiviews

Serving a directory outside DocumentRoot with Apache

I want exampleapp.com/clientapp/ to execute the index.php in /usr/local/apache/htdocs/clientapp.
This stackoverflow question outlines something similar to what I want to do: https://stackoverflow.com/a/8454/173630
I'm having some trouble getting this working. Here's the start of my VirtualHost setup:
<VirtualHost exampleapp.com:80>
DocumentRoot /home/platform/src/serverapp/public
RewriteEngine On
Alias /clientapp/ "/usr/local/apache/htdocs/clientapp"
<Directory "/usr/local/apache/htdocs/clientapp">
FallbackResource index.php
<IfModule mod_suphp.c>
suPHP_UserGroup nobody nobody
</IfModule>
</Directory>
RewriteRule ^/clientapp/(.*)$ /clientapp/$1 [PT]
I'm using Apache 2.2.22. I know this is kind of a confusing setup -- the reason I'm doing this is to avoid cross-domain AJAX requests from clientapp to serverapp.
With this configuration I'm not getting any errors, it's just falling through to the server app.
Update
The problem was that I had a BasicAuth set up on /usr/local/apache/htdocs/clientapp, and the password wasn't being prompted for when visiting exampleapp.com/clientapp/ and it was just silently failing. I took off the BasicAuth for now, which gets it to work.
After trying a few things out, it looks like this is just mod_alias being retarded and either blindly mashing together file-path and URI-path or mistaking the file-path (/usr/local/apache/htdocs/clientapp) for a URI-path (not sure how). Either way, you can do one of two things, it looks like.
Add a trailing slash to your file-path:
Alias /clientapp/ "/usr/local/apache/htdocs/clientapp/"
Remove the trailing slash from your URI-path:
Alias /clientapp "/usr/local/apache/htdocs/clientapp"
Both seems to do the trick, but I would suggest doing the second option, as it would match requests for exampleapp.com/clientapp (no trailing slash), and mod_dir will properly recognize it as a directory and redirect you to exampleapp.com/clientapp/. Whereas if you go with first option, going to exampleapp.com/clientapp would just give you a 404 (or something in the document root ends up handling it).
Change <Directory ...>...</Directory> to <Location /clientapp>...</Location> and keep everything inside it.

mod_rewrite rule broken if PHP file is named as the rewrite pattern

I want to redirect all requests like:
/xml/doSomething?arg=value
To:
/xml.php?action=doSomething&arg=value
I tried this simple rule:
RewriteEngine
RewriteBase /
RewriteRule ^xml/([^/]+)[/]? xml.php?action=$1 [R=302,L,QSA]
But it not works. The xml.php is executed with arg=value param only. The problem is that there is that file named xml.php, as the first part of my rule. In fact, if I change the rule to:
RewriteRule ^asd/([^/]+)[/]? xml.php?action=$1 [R=302,L,QSA]
And I point to:
/asd/doSomething?arg=value
I'm correctly redirected to:
/xml.php?action=doSomething&arg=value
How the presence of a PHP file named as the first part of my rewrite pattern can break it all?
I solved. The problem is that I had Options MultiViews in my virtual host configuration. I did not know about this option:
A MultiViews search is enabled by the MultiViews Options. If the server receives a request for /some/dir/foo and /some/dir/foo does not exist, then the server reads the directory looking for all files named foo.*
That simply explain why my rule does not work.

Apache Mod_ReWrite Suddenly Stopped Working

I had mod_rewrite set on my server to rewrite a url like the following
http://www.example.com/1
to
http://www.example.com/index.php?show=1
In order words a URL shortern. Everything was working fine when the system was running under a sub-domain on my development site, but now it just generates a Not Found error, although if I manually enter the url /index.php?show=1 it works fine.
So the only changes is the urls switching from
http://www.site.example.com
to
http://www.site.com
however it's still running on the same server and the same sub-folder inside public_html on the server just the new domain name has been pointed to that folder.
The folder it's stored in is /public_html/paste
The full .htaccess file running in the directory is
# Set Default File
DirectoryIndex index.php
# Turn ReWrite Engine On
RewriteEngine on
# Create Rule To Write URLs To Shorter Versions
RewriteRule /([a-z0-9]+) /index.php?show=$1
I can't enable RewriteLog as the hosting doesn't allow it for some reason.
It sounds like the AllowOverride directive is not properly set for that folder. In your Apache configuration, you should make sure that the Directory or Vhost you're using for the primary domain has the AllowOverride set to All
http://httpd.apache.org/docs/2.0/mod/core.html#allowoverride
You probably need to specify the RewriteBase directive.
http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritebase
I'll also note that Options +FollowSymlinks would be good to have in there too in case you ever turn it off further up the config chain (rewrite wont work without it).

mod_rewrite 'add path info postfix:'

Why is my mod_rewrite doing this?
add path info postfix: /home/mobelluk/public_html/about.php -> /home/mobelluk/public_html/about.php/
which results in an unwanted trailing slash on EVERYTHING.
I have disabled all my .htaccess rules so they're out of the equation.
apparently there's been an issue with mod_rewrite re-appending post-fix part in certain cases
https://issues.apache.org/bugzilla/show_bug.cgi?id=38642
The problem:
If multiple RewriteRules within a .htaccess file match, unwanted copies of PATH_INFO may accumulate at the end of the URI.
If you are on Apache 2.2.12 or later, you can use the DPI flag to prevent this
http://httpd.apache.org/docs/2.2/rewrite/flags.html
In searching for "add path info postfix", this question comes up first and while it eventually did solve my problem, it took me almost 2 hours to understand what was going on.
In working on a site, I needed this rewrite:
/resources/band/ -> resources.html?section=band
Accomplished with this mod_rewrite:
RewriteRule ^resources/(.*)/$ resources.html?section=$1 [L]
Changing that to [DPI] did nothing... The code on my resources.html page was 100% for sure being called but the argument of section=band was not being sent to it.
Get this... in case you find Apache's documentation impossible to read, Multiviews is the problem. When the browser sees that multiviews is on the server sees /resources/band/ and say "Oh, I'm so smart, I know what that means!" and redirects:
/resources/band/ -> /resources.html/band/
True story! I changed the +Multiviews to -Multiviews on the virtual host - problem instantly solved.
Is it possible the new server has mod_dir loaded, with DirectorySlash On where the old one did not and that is leading to this problem?
(Note that DirectorySlash On is the default if mod_dir is loaded and nothing is overriding it)
I solved this issue by disabling MultiViews in my virtual host Options configuration. I was rewriting something similar to below:
Desired rewrite:
/dir/ -> /dir.html
Actual translations:
/dir/ -> /dir.html (MultiViews)
/dir.html -> /dir.html/ (mod_rewrite: 404, didn't exist)
Disabling MultiViews kept the initial translation from taking place. I could have probably adjusted the rewrite rule to compensate for this, but I wasn't using MultiViews for anything else anyway.
The following post tipped me off on this issue:
https://velenux.wordpress.com/2012/07/17/apache-mod_rewrite-multiple-add-path-info-postfix/#comment-1476