Guzzle and Stack Exchange API, parsing error "JSON_ERROR_UTF8" - php

I'm trying to consume the Stack Exchange API with Guzzle. I am facing an issue where I can't get the JSON response back: it apparently fails when parsing it.
Here is my code:
$client = new GuzzleHttp\Client();
$parameters = ['pagesize'=>'2','order'=>'desc','sort'=> 'activity','q'=>'laravel eloquent','site'=>'stackoverflow'];
$response = $client->get('http://api.stackexchange.com/2.2/search/advanced',['query' => $parameters ]);
The resultant effective URL that Guzzle creates is correct: if you open the link in your browser you'll see that it works fine and returns the requested data.
However, Guzzle fails with this error when trying to access the JSON with $response->json():
GuzzleHttp \ Exception \ ParseException
Unable to parse JSON data: JSON_ERROR_UTF8 - Malformed UTF-8 characters, possibly incorrectly encoded
After reading the documentation again, I believe that the request is compressed and I am not passing the appropriate content header. If this is so, can you please let me know which header I should be passing to get the correct response?

Ok so the following code works for me.
$client = new GuzzleHttp\Client();
$parameters = ['pagesize'=>'2','order'=>'desc','sort'=> 'activity','q'=>'laravel eloquent','site'=>'stackoverflow'];
$params = http_build_query($parameters);
$request = $client->createRequest('GET', 'http://api.stackexchange.com/2.2/search/advanced?'.$params);
$request->addHeader('Accept-Encoding','GZIP');
$request->addHeader('Content-Type','application/json');
$response = $client->send($request);
var_dump($response->json());

Related

getHeader from getInternalResponse in Symfony Panther always return an empty array

By using Symfony Panther, I sent a request and I wanted to get the response. I was able to get the body and the status code but for the header I just got an empty array.
$client = Client::createChromeClient();
$client->request('GET', 'https://google.com');
$client->getInternalResponse()->getHeaders(); // returned empty array!!!
Panther does not have access to the HTTP response as explained in this github issue https://github.com/symfony/panther/issues/17.
But if you read carefuly, you'll see that this is not a limitation of Panther but a limitation of Selenium WebDriver. See this post How to get HTTP Response Code using Selenium WebDriver.
This means that the answer to the question "Can I have access to the HTTP response code or the HTTP header using Symfony Panther?" is "No, it's not possible".
While this is not possible the workaround I found was to create an HttpClient and use it to make a request and get the response from it.
<?php
use Symfony\Component\HttpClient\HttpClient;
$client = HttpClient::create();
$response = $client->request('GET', $this->myBaseUri);
$statusCode = $response->getStatusCode();
$headers = $response->getHeaders();
Here's the documentation for HTTP Client (Symfony Docs) if you want to try this way.
According to this issue: https://github.com/symfony/panther/issues/67, it seems that status code is not managed ( HTTP 200 will always get returned, no matter what the request actually responded.)
And same for the headers, I'm afraid. If you look at class
Symfony\Component\Panther\Client and method get($url) you can see that:
$this->internalResponse = new Response($this->webDriver->getPageSource());
while Response's constructor accepts:
public function __construct(string $content = '', int $status = 200, array $headers = [])
Having these said, no matter what happens, you always get HTTP 200 and empty header array.

DELETE request with parameters using Guzzle

I have to do a DELETE request, with parameters, in the CodeIgnitor platform. First, I tried using cURL, but I switched to Guzzle.
An example of the request in the console is:
curl -X DELETE -d '{"username":"test"}' http://example.net/resource/id
But in the documentation of Guzzle they use parameters just like GET, like DELETE http://example.net/resource/id?username=test, and I don't want to do that.
I tried with:
$client = new GuzzleHttp\Client();
$client->request('DELETE', $url, $data);
but the request just calls DELETE http://example.com/resource/id without any parameters.
If I interpret your curl request properly, you are attempting to send json data as the body of your delete request.
// turn on debugging mode. This will force guzzle to dump the request and response.
$client = new GuzzleHttp\Client(['debug' => true,]);
// this option will also set the 'Content-Type' header.
$response = $client->delete($uri, [
'json' => $data,
]);
coming late on this question after having same.
Prefered solution, avoiding debug mode is to pass params in 'query' as :
$response = $client->request('DELETE', $uri, ['query' => $datas]);
$datas is an array
Guzzle V6
$response = json_decode($this->client->delete($uri,$params)->getStatusCode());
echo $response;
This will also give the status of the response as 204 or 404

How to keep LineFeed in GuzzleHttp Response Body

I am doing and cUrl request using Guzzle.
$client = new GuzzleHttp\Client();
try {
$response = $client->get($url);
} catch (\GuzzleHttp\Exception\RequestException $ex) {
// handle error.
}
The server response is formatted like this:
"field1","field2","field3"\n
"value1","value2","value3"\n
"value4","","value5"\n
Using GuzzleHttp\Client, I receive the following response body
"field1","field2","field3""value1","value2","value3""value4","","value5"\n
Is it possible to set the Guzzle Client not to replace line feed chars in the response body?
We don't know what your response looks like.
We don't know how you are viewing the response.
In the presence of these two details I would have to guess that you might have to implement some type of stream decorator so that only single lines of the response are read in at a time.

Guzzle throws 401 or 406 exception

cURL works fine:
curl -H "X-ApiToken: myapitoken" https://api.fulcrumapp.com/api/v2/records
Guzzle does not:
$client = new Client();
$request = $client->createRequest('GET', "https://api.fulcrumapp.com/api/v2/records");
$request->setHeader("X-ApiToken:" , "myapitoken");
$response = $client->send($request);
This responds with a 401 error: not authorized. This is my first time using Guzzle but in my searches I haven't seen this error. Seems like a simple request so I'm not sure why it is failing.
Thank you!
I had to add another header to explicitly tell it to handle json
$request->setHeader("Accept" , "application/json");
Thank you for pointing out that the 401 was a false error - the real error was the 406, which made me read how to actually fix that.
The setHeader method takes the header name without the colon. Change "X-ApiToken:" to "X-ApiToken".

GuzzleHttp\Client returning 404

I have started to use GuzzleHttp\Client and I have problem to get response from REST API, because I am getting error 404 code. I don't understand it because when I copied url from my code and paste into browser I will see json response. Do you have any idea what I am doing wrong?
$client = new GuzzleHttp\Client();
$response = $client->get('http://login:password#url_to_api/get/some_products');
$json = $response->json();
I don't think, that you can add your login credentials like that.
Here is the right way: http://guzzle.readthedocs.org/en/latest/clients.html#auth

Categories