Guzzlehttp - How get the body of a response from Guzzle 6?
Solution 1
Guzzle implements PSR-7. That means that it will by default store the body of a message in a Stream that uses PHP temp streams. To retrieve all the data, you can use casting operator:
$contents = (string) $response->getBody();
You can also do it with
$contents = $response->getBody()->getContents();
The difference between the two approaches is that getContents
returns the remaining contents, so that a second call returns nothing unless you seek the position of the stream with rewind
or seek
.
$stream = $response->getBody();
$contents = $stream->getContents(); // returns all the contents
$contents = $stream->getContents(); // empty string
$stream->rewind(); // Seek to the beginning
$contents = $stream->getContents(); // returns all the contents
Instead, usings PHP's string casting operations, it will reads all the data from the stream from the beginning until the end is reached.
$contents = (string) $response->getBody(); // returns all the contents
$contents = (string) $response->getBody(); // returns all the contents
Documentation: http://docs.guzzlephp.org/en/latest/psr7.html#responses
Solution 2
If expecting JSON back, the simplest way to get it:
$data = json_decode($response->getBody()); // returns an object
// OR
$data = json_decode($response->getBody(), true); // returns an array
json_decode()
will automatically cast the body to string
, so there is no need to call getContents()
.
Solution 3
For get response in JSON format :
1.
$response = (string) $res->getBody();
$response =json_decode($response); // Using this you can access any key like below
$key_value = $response->key_name; //access key
$response = json_decode($res->getBody(),true);
$key_value = $response['key_name'];//access key
Related videos on Youtube
Comments
-
Greg about 3 years
I'm trying to write a wrapper around an api my company is developing. It's restful, and using Postman I can send a post request to an endpoint like
http://subdomain.dev.myapi.com/api/v1/auth/
with a username and password as POST data and I am given back a token. All works as expected. Now, when I try and do the same from PHP I get back aGuzzleHttp\Psr7\Response
object, but can't seem to find the token anywhere inside it as I did with the Postman request.The relevant code looks like:
$client = new Client(['base_uri' => 'http://companysub.dev.myapi.com/']); $response = $client->post('api/v1/auth/', [ 'form_params' => [ 'username' => $user, 'password' => $password ] ]); var_dump($response); //or $resonse->getBody(), etc...
The output of the code above looks something like (warning, incoming wall of text):
object(guzzlehttp\psr7\response)#36 (6) { ["reasonphrase":"guzzlehttp\psr7\response":private]=> string(2) "ok" ["statuscode":"guzzlehttp\psr7\response":private]=> int(200) ["headers":"guzzlehttp\psr7\response":private]=> array(9) { ["connection"]=> array(1) { [0]=> string(10) "keep-alive" } ["server"]=> array(1) { [0]=> string(15) "gunicorn/19.3.0" } ["date"]=> array(1) { [0]=> string(29) "sat, 30 may 2015 17:22:41 gmt" } ["transfer-encoding"]=> array(1) { [0]=> string(7) "chunked" } ["content-type"]=> array(1) { [0]=> string(16) "application/json" } ["allow"]=> array(1) { [0]=> string(13) "post, options" } ["x-frame-options"]=> array(1) { [0]=> string(10) "sameorigin" } ["vary"]=> array(1) { [0]=> string(12) "cookie, host" } ["via"]=> array(1) { [0]=> string(9) "1.1 vegur" } } ["headerlines":"guzzlehttp\psr7\response":private]=> array(9) { ["connection"]=> array(1) { [0]=> string(10) "keep-alive" } ["server"]=> array(1) { [0]=> string(15) "gunicorn/19.3.0" } ["date"]=> array(1) { [0]=> string(29) "sat, 30 may 2015 17:22:41 gmt" } ["transfer-encoding"]=> array(1) { [0]=> string(7) "chunked" } ["content-type"]=> array(1) { [0]=> string(16) "application/json" } ["allow"]=> array(1) { [0]=> string(13) "post, options" } ["x-frame-options"]=> array(1) { [0]=> string(10) "sameorigin" } ["vary"]=> array(1) { [0]=> string(12) "cookie, host" } ["via"]=> array(1) { [0]=> string(9) "1.1 vegur" } } ["protocol":"guzzlehttp\psr7\response":private]=> string(3) "1.1" ["stream":"guzzlehttp\psr7\response":private]=> object(guzzlehttp\psr7\stream)#27 (7) { ["stream":"guzzlehttp\psr7\stream":private]=> resource(40) of type (stream) ["size":"guzzlehttp\psr7\stream":private]=> null ["seekable":"guzzlehttp\psr7\stream":private]=> bool(true) ["readable":"guzzlehttp\psr7\stream":private]=> bool(true) ["writable":"guzzlehttp\psr7\stream":private]=> bool(true) ["uri":"guzzlehttp\psr7\stream":private]=> string(10) "php://temp" ["custommetadata":"guzzlehttp\psr7\stream":private]=> array(0) { } } }
The output from Postman was something like:
{ "data" : { "token" "fasdfasf-asfasdfasdf-sfasfasf" } }
Clearly I'm missing something about working with the response objects in Guzzle. The Guzzle response indicates a 200 status code on the request, so I'm not sure exactly what I need to do to retrieve the returned data.
-
Federkun almost 9 years
$response->getBody()->getContents()
doesn't work?
-
-
Maximus over 8 yearsThe getContents function is only in one small part of the Guzzle 6 documentation (in the streams section), and I missed it. You saved me from a whole lot of searching.
-
John over 8 yearsTHANK YOU. It's unbelievable that this is not more clear in the documentation. Even their official documentation (docs.guzzlephp.org/en/latest) makes it seem like calling $res->getBody() returns what you would normally expect.
-
cwhsu over 7 yearsThey should really put something like a note or notice in the official documents. I wasted two days on this issue.
-
Magnus over 7 years+1 The Guzzle documentation falsely states that
"you can pass true to this method [getBody()] to retrieve the body as a string."
. That doesn't seem to work for me using Guzzle 6, but casting to string or using getContents() does work. -
Federkun over 7 years@BadCash that's the documentation for guzzle3
-
Magnus over 7 years@Federkun I see, thanks! However, that's the documentation that ranks at the top of Google when searching for "guzzle getbody string", so I guess I'm not the only one being led astray by it. Especially since the only thing indicating that it's for a specific older version is a "3" in the URL...
-
Sygon over 6 yearsYou can also use json_decode. For example wrap your response in
json_decode($response, true);
this will return an array. -
Raccoon almost 6 yearsGod... i wastest several hours because of this... thanks
-
Melroy van den Berg over 5 yearsYou could also take a look at this example, by using middle-ware: stackoverflow.com/questions/30530172/…
-
Akio about 5 years
$response->getBody()->getContents();
returns with a HTTP header in array form. Anyone knows how to fix this? More on this: stackoverflow.com/questions/56004396/… -
Shardj over 4 yearsHighly recommend you don't use (string) $response->getBody() as it doesn't actually retrieve all data. It retrieves the length of the default, so it could truncate the actual value. github.com/guzzle/guzzle/issues/1610
-
Eric McWinNEr over 4 yearsWhy isn' this answer getting more attention??? This is precisely what I needed. Thanks @MaskimIvanov
-
Alator about 4 yearsThat was the most simple and easy thing for me too. Thanks
-
j13k over 3 yearsThis simple answer 'solves' the immediate problem, but it misses the nuance of the accepted answer by @Federkun. The reason this 'just works' most of the time is because the call to
json_decode
implicitly casts the response body as a string. Having said that, it is worth understanding the accepted answer, as there can be problems with the string casting approach not always retrieving all data, as highlighted in the comment by @Shardj. -
Вася Аристов over 3 yearsThis method works but it will cause errors during static analysis
-
Maksim Borodov about 3 years@Shardj How can i retrive all content? My content truncating.
-
Shardj about 3 years@MaksimBorodov I believe the solution is in the comments of the github issue I linked previously
-
Catto over 2 yearsThanks!! I just missed the true keyword
-
Szczepan Hołyszewski about 2 yearsFinding this answer early in my quest saved me hours of hair pulling. One HUGE gotcha: if you have set up request logging using
Middleware::log()
, and the message formatter uses{res_body}
anywhere in the format string, then body WILL have been read by the time you get the response object, and$response->getBody()->getContents()
WILL return an empty string even though YOU haven't read the body!