Guzzle: Access uploaded files in history middleware

618 Views Asked by At

I'm trying to access an uploaded file in the history middleware for Guzzle (v6).

My actual code receives a request (so is using the ServerRequestInterface), then uses Guzzle to send the request elsewhere.

I'm trying to test uploaded files going through this layer, but I can't seem to access them in the Request object returned by Guzzle's middleware.

Example code:

<?php


use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7\ServerRequest;
use GuzzleHttp\Psr7\UploadedFile;

class DoNotCommitTest extends \PHPUnit\Framework\TestCase
{
    public function testUploads()
    {
        $request = new ServerRequest('GET', 'http://example.com/bla');

        $file = new UploadedFile('test', 100, \UPLOAD_ERR_OK);

        $request = $request->withUploadedFiles([$file]);
        $this->assertCount(1, $request->getUploadedFiles());

        // Mock Guzzle request, assert on the request it 'sent'

        $mock = new MockHandler([
            function (ServerRequest $request, array $options) {
                // This fails...
                $this->assertCount(1, $request->getUploadedFiles());
            }
        ]);

        $historyContainer = [];
        $history = Middleware::history($historyContainer);

        $handler = HandlerStack::create($mock);
        $handler->push($history);

        $client = new Client(['handler' => $handler]);

        $client->send($request);
    }
}
1

There are 1 best solutions below

1
On BEST ANSWER

If you follow execution chain, $client->send($request) at some point calls private applyOptions function, which calls Psr7\modify_request function. If you look at Psr7\modify_request function:

...
if ($request instanceof ServerRequestInterface) {
    return new ServerRequest(
        isset($changes['method']) ? $changes['method'] : $request->getMethod(),
        $uri,
        $headers,
        isset($changes['body']) ? $changes['body'] : $request->getBody(),
        isset($changes['version'])
            ? $changes['version']
            : $request->getProtocolVersion(),
        $request->getServerParams()
    );
}
...

It returns new ServerRequest object without preserving your uploaded files array (ServerRequest object doesn't have the uploadedFiles as an argument in the constructor). That's why you lost your uploadedFiles array.

UPDATE:

I created an issue and a pull request to fix it.