PEAR is archived and read-only

This mirror preserves historical PEAR package releases and metadata so existing references remain available.

Home » HTTP » HTTP_Request2 » Bug #5735

No "true" timeout exists

Details

Request #5735No "true" timeout exists
Submitted2005-10-20 19:46 UTC
Fromseth at pricepages dot org
Assignedavb
StatusClosed
PackageHTTP_Request2
PHP Version4.4.0
OSMac
Roadmaps0.2.0

Comments

[2005-10-20 19:46 UTC] seth at pricepages dot org

Description:
------------
I'm not sure if this is a bug or a feature request, but
although there exists two timeout options in HTTP_Request,
it can be delayed indefinitely.

This is done by sending a little data at a time. The
documentation says:
"timeout - Connection timeout in seconds"
"readTimeout - Timeout for reading / writing data over the
socket"

It seems to imply that there is a true way to limit the
connection time, but there is not. (Leading to some of my
pages taking a 22 seconds to render.)

I think that the way to be the most BC would be to make a
third timeout option that limits the total time taken
(including connection time and redirects). This option could
be checked after each socket read. If requested, I could
implement this.

Test script:
---------------
test.php:
<?php
require_once('PEAR.php');
require_once('HTTP/Request.php');
$url = 'http://pricepages.org/pear/slow_page.php';
$req = new HTTP_Request($url, array(
'timeout' => 2,
'readTimeout' => array(2,0)));
$req->sendRequest();
?>

slow_page.php:
<?php
sleep(1);

ob_end_flush();
for($i = 0; $i < 100; $i++){
echo "a big block of text, just rendered ";
flush();
usleep(100000);
}

?>

Expected result:
----------------
$ time php -f test.php

real 0m2.000s
user 0m0.085s
sys 0m0.059s

Actual result:
--------------
$ time php -f test.php

real 0m12.258s
user 0m0.085s
sys 0m0.059s

[2005-11-08 05:17 UTC] seth at pricepages dot org

Would the best way to do this be to readAll() from the
socket in non-blocking mode and then after each read, check
the utime? (That is the best I can think of.)

There would also need to be another option passed into the
constructor for the true timeout time. (Instead of the other
fake times :)

[2005-11-08 17:31 UTC] seth at pricepages dot org

Please excuse any of my ignorance, I haven't worked at the
socket level before. (Well, only once, and that was for a
Comp. Sci. class.)

I think the problem that I am having with the listener is
that I don't see how the listener can respond to an expired
timeout. It can check the elapsed time, but it can't do
anything about it without changing the interface between the
Response and the Listener classes. Also, no ticks are called
during the reading of the header (from what I can tell from
the code).

I suppose I could add a "shouldEndRequest()" method to the
Listener class that returns a boolean, but you run into
problems with multiple listeners, or calling
Request::getResponseBody
after a listener ends the request. It just seems like it
opens up a big can of unpredictable behavior.

Also, how would the Listener deal with setting the socket's
timeout so the various Socket::readLine calls would return
at an appropriate time? Instead of shouldEndRequest, we
could use timeRemaining, and for each readLine call, set the
socket timeout to be the time returned from timeRemaining.

The best way that I see it working is if the code is
located in the request and response classes.

However, if you prefer shouldEndRequest or timeRemaining,
I'd be willing to work on it.

[2006-10-11 11:01 UTC] lobbin at gmail dot com

This is related to a problem with readTimeout I'm having.

As far as I've debugged this. HTTP_Request sets this on Net_Socket which uses stream_set_timeout , but something probably in Net_Socket or PHP makes the timeout not work, however, it works with the really small example available on stream_set_timeout manual page.