Skip to content
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

Only read up to Content-Length in stream wrapper #1510

Merged
merged 2 commits into from Jul 1, 2016

Conversation

mtdowling
Copy link
Member

This commit updates the stream wrapper to only read up to the number of
bytes returned in the Content-Length header when draining a stream
synchronously.

@Yanacek @Tobion

@mtdowling
Copy link
Member Author

Note that the test failure is due to an unrelated change in a package Guzzle depends on. @Tobion is addressing this issue.

$this->drain(
$stream,
$sink,
$response->getHeaderLine("Content-Length")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think single quotes are used so far

Copy link
Member

@Tobion Tobion Jun 30, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe something like is_numeric($response->getHeaderLine('Content-Length') ? (int) $response->getHeaderLine('Content-Length') : -1 then you can just pass this length to copy_to_stream

@mtdowling
Copy link
Member Author

Good feedback, @Tobion. I've pushed up a commit to address the feedback.

Psr7\copy_to_stream(
$source,
$sink,
strlen($contentLength) > 0 ? (int) $contentLength : -1
Copy link
Member

@Tobion Tobion Jun 30, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Content-Length is not numeric (which would be invalid), it will cast to 0. Not sure if that is wanted.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, that's probably ideal. It would prevent us from being able to read any data, which is better than reading until a timeout.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An actual contentLength of 0, or one that is cast to 0 seems to be causing issues with fread in the Psr7 package, see issue #1539.

I hit this fread warning today when calling some AWS API commands which caused my Laravel app to bomb out.

@Tobion
Copy link
Member

Tobion commented Jun 30, 2016

Responses to HEAD requests can sent a Content-Length header that is not actually the size of the response body:

in the case of the HEAD method, the size of the entity-body that would have been sent had the request been a GET.

Is it handled somewhere that certain status codes or HEAD responses must not have a body?

@Tobion
Copy link
Member

Tobion commented Jun 30, 2016

Looking at the implementation of copy_to_stream ( https://github.com/guzzle/psr7/blob/master/src/functions.php#L385 ) it seems that it will require the amount of memory that is given with the maxLength size. So if the response is 1 GB, it will also require 1 GB of memory to copy the stream. This doesn't seem right. Shouldn't it read the stream in batches just as it is done when $maxLen === -1?

@mtdowling
Copy link
Member Author

Yeah, this is not taking HEAD requests into account. I'll push a fix.

As for copy_to_stream, you're right. The implementation could be improved.

This commit updates the stream wrapper to only read up to the number of
bytes returned in the Content-Length header when draining a stream
synchronously.
@mtdowling
Copy link
Member Author

No longer draining the stream for HEAD requests. The poor maxLen implementation can be addressed separately on the PSR-7 repo. Rebased on master, so hopefully the tests will pass now.

@Tobion
Copy link
Member

Tobion commented Jun 30, 2016

createSink still fopens a stream even for HEAD requests (and the source stream is not closed anymore for head request). This doesn't seem necessary. I think you could just use the source stream as response body then (as it is done when $options['stream'] is true`).

@mtdowling
Copy link
Member Author

Nice catch. I pushed a commit to no longer create a new sink when sending a HEAD request.

$this->drain($stream, $sink);
// Do not drain when the request is a HEAD request because they have
// no body.
if ($hasResponseBody && $sink !== $stream) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$hasResponseBody seems useless as the second condition is never true in this case anyway

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. Fixed.

@Tobion
Copy link
Member

Tobion commented Jul 1, 2016

👍

@mtdowling mtdowling merged commit 10a49d5 into master Jul 1, 2016
@mtdowling mtdowling deleted the stream-read-content-length branch July 4, 2016 05:52
camlafit pushed a commit to spip/spip that referenced this pull request Nov 27, 2023
…nt-length envoyé par le serveur pour arrêter la lecture du stream des qu'on a atteint cette longueur et eviter de timeout en demandant plus de contenu sur un serveur mal configuré

Cf guzzle/guzzle#1510 et guzzle/guzzle#1577
Refs: #5769
camlafit pushed a commit to spip/spip that referenced this pull request Dec 15, 2023
…nt-length envoyé par le serveur pour arrêter la lecture du stream des qu'on a atteint cette longueur et eviter de timeout en demandant plus de contenu sur un serveur mal configuré

Cf guzzle/guzzle#1510 et guzzle/guzzle#1577
Refs: #5769
camlafit pushed a commit to spip/spip that referenced this pull request Dec 15, 2023
…nt-length envoyé par le serveur pour arrêter la lecture du stream des qu'on a atteint cette longueur et eviter de timeout en demandant plus de contenu sur un serveur mal configuré

Cf guzzle/guzzle#1510 et guzzle/guzzle#1577
Refs: #5769
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants