How do I get the body of SENT data with Guzzle PHP?

My solution for Laravel from 5.7:

MessageFormatter works with variable substitutions, see this: https://github.com/guzzle/guzzle/blob/master/src/MessageFormatter.php

     $stack = HandlerStack::create();
        $stack->push(
            Middleware::log(
                Log::channel('single'),
                new MessageFormatter('Req Body: {request}')
            )
     );

    $client = new Client();
    $response = $client->request(
        'POST',
        'https://url.com/go',
        [
            'headers' => [
                "Content-Type" => "application/json",
                'Authorization' => 'Bearer 123'
            ],
            'json' => $menu,
            'handler' => $stack
        ]
    );

You can do this work by creating a Middleware.

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Psr\Http\Message\RequestInterface;

$stack = HandlerStack::create();
// my middleware
$stack->push(Middleware::mapRequest(function (RequestInterface $request) {
    $contentsRequest = (string) $request->getBody();
    //var_dump($contentsRequest);

    return $request;
}));

$client = new Client([
    'base_uri' => 'http://www.example.com/api/',
    'handler' => $stack
]);

$response = $client->request('POST', 'itemupdate', [
    'auth' => [$username, $password],
    'json' => [
        "key" => "value",
        "key2" => "value",
    ]
]);

This, however, is triggered before to receive the response. You may want to do something like this:

$stack->push(function (callable $handler) {
    return function (RequestInterface $request, array $options) use ($handler) {
        return $handler($request, $options)->then(
            function ($response) use ($request) {
                // work here
                $contentsRequest = (string) $request->getBody();
                //var_dump($contentsRequest);
                return $response;
            }
        );
    };
});

Using Guzzle 6.2.

I've been struggling with this for the last couple days too, while trying to build a method for auditing HTTP interactions with different APIs. The solution in my case was to simply rewind the request body.

The the request's body is actually implemented as a stream. So when the request is sent, Guzzle reads from the stream. Reading the complete stream moves the stream's internal pointer to the end. So when you call getContents() after the request has been made, the internal pointer is already at the end of the stream and returns nothing.

The solution? Rewind the pointer to the beginning and read the stream again.

<?php
// ...
$body = $request->getBody();
echo $body->getContents(); // -->nothing

// Rewind the stream
$body->rewind();
echo $body->getContents(); // -->The request body :)

Tags:

Php

Http

Guzzle