php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #60351 Phar::createDefaultStub runs indexfile, not webindexfile parameter
Submitted: 2011-11-21 20:32 UTC Modified: 2016-09-08 23:21 UTC
Votes:4
Avg. Score:3.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: scott at aubrey dot org dot uk Assigned:
Status: Open Package: Built-in web server
PHP Version: 5.4.0RC1 OS: Mac OS X Lion 10.7.2
Private report: No CVE-ID: None
 [2011-11-21 20:32 UTC] scott at aubrey dot org dot uk
Description:
------------
When building a phar, you can use a default stub creator by using 
Phar::createDefaultStub. The first param should run from the CLI, the second from 
a web server.

When using the built in CLI-web server and navigating to the phar, the file in 
the first param is run. When testing on apache the same file, it runs the second 
param.

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

$testPhar = new Phar('test.phar',null, 'test');
$testPhar->addFromString('cli.php', '<?php print "CLI".PHP_EOL;exit;');
$testPhar->addFromString('web.php', '<?php print "web".PHP_EOL;exit;');
$testPhar->setStub($testPhar->createDefaultStub('cli.php','web.php'));


Expected result:
----------------
browser should simple output "web"

Actual result:
--------------
browser shows "CLI" when run from CLI web server

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-11-28 17:39 UTC] reeze dot xia at gmail dot com
Hi, scott:
 1. How can you run .phar file in builtin web server? The server seems can only 
    serve .php file as script file. do you mean rename the .phar file to php ?
 2. After rename the phar file to php doesn't reproduce the wrong error output.

Could you please post more details about the bug ? thx :)
 [2011-11-28 20:07 UTC] scott at aubrey dot org dot uk
Sorry, I hadn't tried it the way you had, and it does indeed work.

But using the phar as the router script is the method I was using, as per 
http://php.net/manual/en/features.commandline.webserver.php#example-361 

This does fail as described, even with a phar ending .php.
 [2011-12-06 16:58 UTC] reeze dot xia at gmail dot com
Hi, scott:
    I got your idea, you use phar file as router script. by look into the builtin 
server. the route script is a simple script executed before server decide whether 
to server the php page or not. so In my opinion, the router file is **INDEED** run 
in cli mode instead of web mode. so the behavior is expected ;-)

So I think this bug can change to Not Bug, what do you think?
 [2011-12-06 20:38 UTC] scott at aubrey dot org dot uk
That may be what is happening, but It's not what I would expect, nor what the 
documentation says:

"The script is run at the start of each HTTP request. If this script returns 
FALSE, then the requested resource is returned as-is. Otherwise the script's 
output is returned to the browser."
http://php.net/manual/en/features.commandline.webserver.php

So from that description, I would expect the router scripts output to return the 
resource. Using a phar, I would expect the stub to setup the phar for web, and 
using the .phar format default stub I would expect the second argument to do that 
correctly?

Unless I'm way off with my expectations here.
 [2014-12-23 16:14 UTC] eldmannen+php at gmail dot com
You can run the PHAR on the PHP built-in web server using a normal PHP file that does an include.

$ php -S 0.0.0.0:8000

<?php

require 'foo.phar';
 [2014-12-31 21:18 UTC] scott at aubrey dot org dot uk
@ eldmannen+php at gmail dot com

It's been a good while since I've played with this, but my test still shows "CLI" in the output after setting up as you said. 

However I can sort of get it to work how I expect by following these steps.

create the test script as original report, and run on the cli to create the phar:

php -d phar.readonly=0 test.php

run the built in server with the router script:

php -S 127.0.0.1:8080 test.phar

then visit http://127.0.0.1:8080/test.phar or http://127.0.0.1:8080/test.phar/web.php with the built in server and you'll get "web". If you visit http://127.0.0.1:8080/, it fails again, showing "CLI".

My *guess* from this testing, and from fiddling with the default stub created, is that when Phar::webPhar() is called from the stub, it *expects* the REQUEST_URI to begin with the phar's filename before it will process as a web request. This is evidenced by the phar router working only when visiting /test.phar. 

The default stub expects that if Phar::webPhar() doesn't handle it, then next thing to do is show the other, non-web script. So any other URI not starting with /test.phar shows "CLI" even though it's run from the same web server.

It would be better if Phar::webPhar() could detect if it's been run from a web context some other way. Maybe if $_SERVER['REQUEST_URI'] is set at all, or even just where php_sapi_name() !== "cli"? Any other ideas?

As an example, if you replace the default stub with this:
<?php

Phar::interceptFileFuncs();
set_include_path('phar://' . __FILE__ . PATH_SEPARATOR . get_include_path());

if (php_sapi_name() === "cli") {
    include 'phar://' . __FILE__ . '/' . 'cli.php';
    return;
}
include 'phar://' . __FILE__ . '/' . 'web.php';
return;

__HALT_COMPILER();
?>

it works as a router script, and from the CLI, showing "web" and "CLI" respectively.
 [2014-12-31 21:19 UTC] scott at aubrey dot org dot uk
forgot to say, all above tested with 5.6.3
 [2015-09-09 15:14 UTC] cmb@php.net
-Status: Open +Status: Feedback -Assigned To: +Assigned To: cmb
 [2015-09-09 15:14 UTC] cmb@php.net
It seems to me, in this case you don't want to use test.phar as
router script. You only want to be able to execute test.phar when
requested from the web server. For Apache you'd have to configure
the respective handler, for the built-in web server you'd have to
use a router script, maybe something like the following:

    <?php
    $ext = pathinfo($_SERVER['SCRIPT_NAME'], PATHINFO_EXTENSION);
    if ($ext == 'phar') {
        include $_SERVER['SCRIPT_NAME'];
        return true;
    } else {
        return false;
    }
    ?>

Then the built-in web server should behave as expected.
 [2015-09-09 19:23 UTC] scott at aubrey dot org dot uk
-Status: Feedback +Status: Assigned
 [2015-09-09 19:23 UTC] scott at aubrey dot org dot uk
Hi

That's just a slight variation on the example given by eldmannen. 

The reason I even tried it in the first place was because I was looking for an easy way to run tests against a phar'd application. Rather than fire up apache, or indeed have an additional route script file, it felt like a really neat trick (with the then new dev server) would be to:

 ./buildPhar.sh                    # Build the Phar file
 php -S localhost:8888 app.phar&   # run server with phar 
 phpunit tests/acceptance          # run tests
 kill $!                           # kill BG server

*I* expected that to work, but it didn't. I personally think being able to just run a phar without additional supporting files is a useful feature, and should be part of the default stub. I've since abandoned using phars to create distributable application anyway

However, I still think it's weird when using the default stub and run as a router `php -S localhost:8888 app.phar` a request to '/' shows the CLI stub script, but a request to '/app.phar' shows the web one. 

Other supporting evidence:
 * no other files are served outside the phar, so it's *not* mapping the URL to the phar file, 
 * running the phar from any directory (php -S localhost:8080 /path/somewhere/else/test.phar) will only show "web" when the URL start with "/test.phar", paths not required.
 * you can craft a trivial replacement phar stub that *does* work how I expect.

It just feels like the default one not doing this is ... well, a bit buggy.

If no-one else finds that at least slightly odd and a bit of a gotcha, fine. I'm not going to use it anyway, and if I was, I'd just work around it by not using the default stub. 

I guess I'm saying: nearly 4 years on, if no one else cares about the first impression of a phar on the dev server, I'm not going to continue arguing for it to change.
 [2016-09-08 23:21 UTC] cmb@php.net
-Status: Assigned +Status: Open -Assigned To: cmb +Assigned To:
 [2016-09-08 23:21 UTC] cmb@php.net
I still didn't find the time to have a closer look at this issue,
and most likely won't in the near future, so I'm leaving that for
somebody else. Sorry.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 13:01:29 2024 UTC