Add 'read_timeout' option#1611
Conversation
| $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.
This could use the RequestOptions constant defined in this PR.
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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.
Ok, done :) Is this guaranteed to work in all cases ?
There was a problem hiding this comment.
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
sagikazarmark
left a comment
There was a problem hiding this comment.
Thanks for the PR. Can you please clarify the few things I mentioned? Thank you very much
| */ | ||
| const TIMEOUT = 'timeout'; | ||
|
|
||
| /** |
There was a problem hiding this comment.
Maybe mention that it's configured in PHP ini?
| res.write("sleeping 60 seconds ...\n"); | ||
| setTimeout(function () { | ||
| res.end("slept 60 seconds\n"); | ||
| }, 10000); |
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.
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.
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.
sagikazarmark
left a comment
There was a problem hiding this comment.
@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.
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.
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.
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