-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add 'read_timeout' option #1611
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a test?
$resource = fopen((string) $request->getUri()->withFragment(''), 'r', null, $context); | ||
$this->lastHeaders = $http_response_header; | ||
|
||
if (isset($options['read_timeout'])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could use the RequestOptions constant defined in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree :)
Other uses of the $options array in this class don't make use of RequestOptions constants, so I tried to keep it consistent.
Do you think I still should use the RequestOptions constant ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right; it's better to keep this consistent.
if (isset($options['read_timeout'])) { | ||
$readTimeout = $options['read_timeout']; | ||
$sec = (int) $readTimeout; | ||
$usec = ($readTimeout - $sec) * 1000000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this always be 0? If a user supplies a readTimeout of 1
, then $usec
will be set to (1 - 1) * 1000000
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If will be > 0 if read_timeout is not an integer:
$readTimeout =1.5;
$sec = (int) $readTimeout; // 1
$usec = ($readTimeout - $sec) * 1000000; // (1.5 - 1) * 1000000 == 5000000
However there is one extra 0 here, I'll fix this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OIC. I didn't realize that stream_set_timeout
required seconds and fractions of seconds to be passed in as separate parameters.
18b9bf5
to
f03ae42
Compare
@jeskew: Thank you for the review. I updated the PR accordingly. |
$this->assertEquals("sleeping 60 seconds ...\n", $line); | ||
$line = fgets($body); | ||
$this->assertFalse($line); | ||
$this->assertFalse(feof($body)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you're using the test server, this should explicitly check whether the stream timed out, e.g., $this->assertTrue(stream_get_meta_data($body)['timed_out']);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, done :) Is this guaranteed to work in all cases ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the PHP docs, this value will be true if the stream has timed out. They don't mention any known exceptions.
14bef88
to
55526fd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR. Can you please clarify the few things I mentioned? Thank you very much
@@ -238,6 +238,12 @@ | |||
const TIMEOUT = 'timeout'; | |||
|
|||
/** | |||
* read_timeout: (float, default=default_socket_timeout) Float describing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe mention that it's configured in PHP ini?
res.write("sleeping 60 seconds ...\n"); | ||
setTimeout(function () { | ||
res.end("slept 60 seconds\n"); | ||
}, 10000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this 60 seconds?
a8e2b71
to
be3ab76
Compare
@sagikazarmark Thank you for the review, I've updated the PR accordingly |
res.write("sleeping 60 seconds ...\n"); | ||
setTimeout(function () { | ||
res.end("slept 60 seconds\n"); | ||
}, 60*1000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am still not 100% sure what's happening here: it says 60 seconds, but in the test the read timeout is only one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The server takes 60 seconds to send the end of the response, and the client has a 1 second read timeout. So the client times out while reading the response.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, okay, thank
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@arnaud-lb can you please add some documentation? Apart from that, ready to go.
be3ab76
to
ed1d1bd
Compare
@sagikazarmark: Awesome, added documentation |
$readTimeout = $options['read_timeout']; | ||
$sec = (int) $readTimeout; | ||
$usec = ($readTimeout - $sec) * 100000; | ||
stream_set_timeout($resource, $sec, $usec); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest I wonder if it would be better to pass the timeout to stream_context_create
. It supports float values so it wouldn't require the magic above. One could even argue that the same functionality is already available via the undocumented stream_context
option. WDYT @arnaud-lb ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it makes the code clearer, I'm all for it :) Which stream context option are you thinking about ? The "http.timeout" context option is used to implement Guzzle's "timeout" option, and I believe that it affects only the connection + reading the headers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, indeed, you are right, missed that.
Thanks for working on this, sorry for the long wait. |
This adds a 'read_timeout' option, allowing the user to specify a read timeout for reads on the body of streamed requests.
Support is added only to the StreamHandler, since only this handler seems to support stream requests.
This fixes #1516