amphp / http-client

An advanced async HTTP client library for PHP, enabling efficient, non-blocking, and concurrent requests and responses.
https://amphp.org/http-client
MIT License
706 stars 66 forks source link

Call to a member function promise() on null #319

Open xpader opened 1 year ago

xpader commented 1 year ago

It's a weird problem

Call to a member function promise() on null in /home/web/apps/t-task-wind/releases/147/vendor/amphp/http-client/src/Connection/Internal/Http2ConnectionProcessor.php:1167

But I see there is check on the code https://github.com/amphp/http-client/blob/4.x/src/Connection/Internal/Http2ConnectionProcessor.php#L1165

kelunik commented 1 year ago

This this an issue you can reproduce?

xpader commented 1 year ago

I don't know how to reproduce this, it happends everyday on my server, not many. Look like it happend sometime on file upload request with FileBody.

xpader commented 7 months ago

Still happends.

Previous Error: Call to a member function promise() on null in /home/web/apps/t-task-wind/releases/298/vendor/amphp/http-client/src/Connection/Internal/Http2ConnectionProcessor.php:1169

xpader commented 4 months ago

I have make a little change to make sure not get a null pendingResponse. Get a prepared pendingResponse and not use $http2stream->pendingResponse

Add code after (before write or read some in async) https://github.com/amphp/http-client/blob/4.x/src/Connection/Internal/Http2ConnectionProcessor.php#L1125

$pendingResponse = $http2stream->pendingResponse;

Change https://github.com/amphp/http-client/blob/4.x/src/Connection/Internal/Http2ConnectionProcessor.php#L1169 to

return yield $pendingResponse->promise();

Now the error has turned into a different kind of situation:

Amp\Http\Client\TimeoutException: Allowed transfer timeout exceeded, took longer than 30000 ms in /home/web/apps/t-task-wind/releases/342/vendor/amphp/http-client/src/Connection/Internal/Http2ConnectionProcessor.php:1104 [] []
xpader commented 4 months ago

I was upload through http proxy with "amphp/http-tunnel": "^1.0", when set request protocol force to 1.1, and upload a large file, get below error after about 15 seconds:

Amp\ByteStream\StreamException: Failed to write to stream after multiple attempts; fwrite(): SSL: Broken pipe in ./vendor/amphp/byte-stream/lib/ResourceOutputStream.php:107

When remove force protocol setting, it will stuck at \Amp\Http\Client\Connection\Internal\Http2ConnectionProcessor::writeBufferedData, position:

        if ($windowSize > 0) {
            // Read next body chunk if less than 8192 bytes will remain in the buffer
            if ($length - 8192 < $windowSize && $stream->windowSizeIncrease) {
                $deferred = $stream->windowSizeIncrease;
                $stream->windowSizeIncrease = null;
                $deferred->resolve();
            }

            $data = $stream->requestBodyBuffer;
            $end = $windowSize - $this->frameSizeLimit;

            $stream->clientWindow -= $windowSize;
            $this->clientWindow -= $windowSize;

            for ($off = 0; $off < $end; $off += $this->frameSizeLimit) {
                $this->writeFrame(
                    Http2Parser::DATA,
                    Http2Parser::NO_FLAG,
                    $stream->id,
                    \substr($data, $off, $this->frameSizeLimit)
                );
            }

            //stuck at writeFrame here:
            $promise = $this->writeFrame(
                Http2Parser::DATA,
                Http2Parser::NO_FLAG,
                $stream->id,
                \substr($data, $off, $windowSize - $off)
            );

            $stream->requestBodyBuffer = \substr($data, $windowSize);
            $stream->enableInactivityWatcher();

            return $promise;
        }
xpader commented 4 months ago

It's be a little strange, sometime it's just stuck there, sometimes it throw error ,Allowed transfer timeout exceeded, took longer than 30000 ms.