php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #67671 mod_rewrite emulation fails for paths with dots in them
Submitted: 2014-07-23 14:25 UTC Modified: 2016-11-02 18:16 UTC
Votes:6
Avg. Score:4.5 ± 0.8
Reproduced:6 of 6 (100.0%)
Same Version:2 (33.3%)
Same OS:2 (33.3%)
From: tobias at twokings dot nl Assigned: cmb (profile)
Status: Not a bug Package: Built-in web server
PHP Version: 5.6.0RC2 OS: Debian GNU/Linux jessie x64
Private report: No CVE-ID: None
 [2014-07-23 14:25 UTC] tobias at twokings dot nl
Description:
------------
I'm using a mod_rewrite configuration that rewrites everything to index.php, like this one:

RewriteEngine On
RewriteRule /index.php - [L]
RewriteRule .* /index.php [L]

...and the test script below.

I request a few URLs, such as:

http://localhost/
http://localhost/asdf
http://localhost/asdf.foo

Testing with command-line cURL, talking to Apache 2.4 (as provided by debian) with mod_php and mod_rewrite, running on localhost:80 in the default vhost, and `php -S localhost:8000`.

Test script:
---------------
<?php

// It's not really relevant what we echo here;
// this is just so we can see whether our script actually get hit
echo $_SERVER['REQUEST_URI'];

Expected result:
----------------
Identical results for apache and the built-in web server.

Actual result:
--------------
The built-in web server responds with a "404 Not Found" for URLs containing dots, instead of echoing the REQUEST_URI.

Sample session:

--------

me@localhost:~/ > curl localhost:80/
/
me@localhost:~/ > curl localhost:80/asdf
/asdf
me@localhost:~/ > curl localhost:80/asdf.foo
/asdf.foo
me@localhost:~/ > curl localhost:8000/
/
me@localhost:~/ > curl localhost:8000/asdf
/asdf
me@localhost:~/ > curl localhost:8000/asdf.foo
<!doctype html><html><head><title>404 Not Found</title><style>
body { background-color: #fcfcfc; color: #333333; margin: 0; padding:0; }
h1 { font-size: 1.5em; font-weight: normal; background-color: #9999cc; min-height:2em; line-height:2em; border-bottom: 1px inset black; margin: 0; }
h1, p { padding-left: 10px; }
code.url { background-color: #eeeeee; font-family:monospace; padding:0 2px;}
</style>
</head><body><h1>Not Found</h1><p>The requested resource <code class="url">/asdf.foo</code> was not found on this server.</p></body></html>

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-07-23 18:24 UTC] requinix@php.net
-Status: Open +Status: Feedback
 [2014-07-23 18:24 UTC] requinix@php.net
Like the other bug, this is working for me as well. Ubuntu 14.04 x64

/path/to/php560rc2/sapi/cli$ ./php -S localhost:8000 -t / router.php
PHP 5.6.0RC2 Development Server started at Wed Jul 23 11:16:15 2014
Listening on http://localhost:8000
Document root is /
Press Ctrl-C to quit.
[Wed Jul 23 11:17:24 2014] serving /asdf.foo

$  curl http://localhost:8000/asdf.foo
5.6.0RC2: /asdf.foo


I suppose the next thing to check is your configure command. Also for the heck of it, the loaded modules and any non-default php.ini settings you may have set.
(I used vanilla ./configure with stock modules and settings)
 [2014-07-23 18:25 UTC] requinix@php.net
Oh, and my router script is

<?php
error_log("serving {$_SERVER["REQUEST_URI"]}");
echo PHP_VERSION . ": ", $_SERVER["REQUEST_URI"], "\n";
 [2014-07-23 20:10 UTC] genesislive2007 at gmail dot com
tring to fix it with this PR:
https://github.com/php/php-src/pull/738
 [2014-07-23 21:29 UTC] requinix@php.net
-Status: Feedback +Status: Open
 [2014-07-23 21:29 UTC] requinix@php.net
Still unsure how to reproduce (and my brain is completely failing to read C right now) but that code certainly does look responsible for it.
 [2014-07-25 05:06 UTC] genesislive2007 at gmail dot com
It's not a bug.
If you want to force the entry point (ot emulate a RewriteRule) you need to fire up the server in this way:
php -S localhost:8000 -t dir dir/index.php
 [2014-07-28 09:26 UTC] tobias at twokings dot nl
> It's not a bug.

If it's not a bug, then it is an undocumented feature that is different from the default behavior of emulating Apache + mod_php. The built-in web server emulates RewriteRules just fine, *except* when the HTTP path contains a dot, in which case it assumes that we want to serve a static file. In other words, what seems to happen here is that the static file detection happens *before* processing rewrites, while in Apache, it happens *after* (or rather, Apache resolves rewrites, then maps the resulting request path to filesystem paths, potentially with MultiViews changing the extension based on acceptable content types, and then determines, based on the file it finds, how to process the result).

Note, specifically, that the built-in server *does* support RewriteRules; it parses .htaccess and processes it correctly.

Either way, whether the request URL contains a dot is completely orthogonal to static file detection: I may want to serve a file named `README` statically under `/README`, and `/domain-info/example.org` could be a dynamic URL that I want to process *exactly* like `/domain-info/all-domains`.

> If you want to force the entry point (ot emulate a RewriteRule) you need to fire up the server in this way

That is hardly a solution. I do not want to force an entry point for everything, the example is just a minimum viable Rewrite configuration to demonstrate the problem. In my real-world example, this won't work at all, because I need to rewrite more specifically, leaving some static files actually served statically. The built-in server *does* support RewriteRule (see above), and the problem is not with those - RewriteRules are merely a triggering circumstance, but the root problem is that the built-in server uses a flawed mechanism to determine whether something should be served statically or not.

Anyway; the point of the built-in web server is to test PHP scripts locally, and any undocumented deviation from a reasonably standard Apache setup is highly undesirable for that, because if the test server doesn't match the production system on key aspects like this one, why bother using it at all?
 [2015-02-18 19:38 UTC] cmbecker69 at gmx dot de
> Note, specifically, that the built-in server *does* support
> RewriteRules; it parses .htaccess and processes it correctly.

I strongly doubt that. It might be possible to use a router script
that caters to .htaccess, though.
 [2015-09-05 17:22 UTC] cmb@php.net
-Status: Open +Status: Not a bug -Assigned To: +Assigned To: cmb
 [2015-09-05 17:22 UTC] cmb@php.net
Firstly, the built-in webserver does not support .htaccess, let
alone any rewrite rules. This is unlikely to change, and certainly
not a bug.

What happens in your case? Requesting <http://localhost/> delivers
index.php, as expected. If <http://localhost/asdf.foo> is
requested, the server responds with 404 Not found, what is also
expected, because the resource doesn't exist.

However, if <http://localhost/asdf> is requested, the server
delivers index.php in the docroot, what is a bug, namely bug
#70434.
 [2016-11-02 16:45 UTC] aljosha dot papsch at vinexus dot eu
This is totally a bug. PHP assumes a path part with a dot is a file. That assumption is not necessarily right. It should be up to application to decide what to do.

PHP can maintain this "dot in a path is a file" assumption but instead of returning the 404 error it should route to router script.
 [2016-11-02 18:16 UTC] cmb@php.net
> PHP assumes a path part with a dot is a file. That assumption is not
> necessarily right.

I agree, and if the built in webserver actually behaves this way, I
think that is a bug (please open another ticket for this).

> PHP can maintain this "dot in a path is a file" assumption but instead
> of returning the 404 error it should route to router script.

It appears there is a misconception regarding router scripts. These are
*always* executed *before* the requested document is served; they do not
work as fallback for 404 (or other) error cases.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sat May 25 19:01:26 2019 UTC