Guzzle throws 401 or 406 exception - php

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".

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.

How to handle 401 Response from Guzzle Client

I make a Guzzle 6 request, and this request responses with a 401.
$client = new Client();
$response = $client->request('GET', ....
....
My Script will stop then and will return a error message.
GuzzleHttp \ Exception \ ClientException (401)
Client error: GET https://.....?lang=de resulted in a 401 Unauthorized response: Unauthorized
Try catch does not work.
How can I intercept the error message?
Thanks for help!
I found the error.
I have added the parameter
'http_errors' => false
http://docs.guzzlephp.org/en/stable/request-options.html#http-errors
Now I can check the response status:
if ($response->getStatusCode() != 200) {
echo "error";
}
We need more code to help you, which parameters you use, what is your request, etc ...
You can try to send your request with Postman to check if your parameter are correcly sended

Laravel 5: Guzzle -> getStatusCode on Exception?

I am programming a little application for myself. This application is calling to different websites with the package Guzzle.
However, I want to store every request in my database with the time and the request duration time and the request status code I get. The problem I am facing here right now is that I don't know how to get the http status code when the request fails..
This is my code so far:
$client = $this->getGuzzleClient();
$request = $client->post($url, $headers, $value);
try {
$response = $request->send();
return $response->getBody();
}catch (\GuzzleHttp\Exception\RequestException $e){
dd(array($e, $e->getResponse()));
}
The $e->getResponse() returns null. I also tried to use $e->getStatusCode() or $e->getRequest()->getStatusCode(). Both are not working...
To be absolutely sure the request is valid and I deal with a real exception I call to this website https://httpstat.us/503. This returns a 503 http status code...
So, how can I get the http status code? Do you guys have any idea?
Kind regards and Thank You!
If you catch a ServerException you are catching a 5xx, if the code execution enters there Guzzle has received a 5xx. If you catch a RequestException that includes network errors too. If the code execution enters on the RequestException but does not on the ServerException means that for Guzzle is not a 5xx error but a network error.
$errorstatuscode=$exception->status;
// to get error code from Excetion Object

Retrieving original body from an http error in Guzzle

I'm making a Guzzle request to an api, and
$request = $this->client->request('GET', 'https://etc', ['http_errors' => false]);
I've had to turn http_errors off as if the API wants to tell me something it does it as a JSON response but it also has a header code of 402.
I can get the response headers back from Guzzle, but I'm unable to get the actual body $request->getBody() as this is just an empty stream on the response object.
Does anyone know how I retrieve the original page despite it providing a 402 http error.
NB: If I don't turn off http_errors, it will throw an exception but the message is wrapped (and truncated).
Any suggestions would be gratefully received.
I stumbled across the answer I was looking for.
If I don't turn off http_errors and catch the exception I can run
$e->getResponse()->getBody()->getContents();
to retrieve the contents of the request.

Why is my Authorization Header giving me a 401 in Guzzle?

I am getting a 401 on Guzzle 4.2 and the same setup works on Postman. Code below.
// Create a client with a base URL
$client = new GuzzleHttp\Client(['base_url' => 'cloud.feedly.com/v3/streams/contents?streamId=user/user-id/category/global.all&count=1']);
// Send a request to https://github.com/notifications
$response = $client->get();
//Auth
$response->addHeader('Authorization', "auth-code");
//send
$r = $response->send();
dd($r->json());
The error is:
GuzzleHttp \ Exception \ ClientException (401)
Client error response [url] cloud.feedly.com/v3/streams/contents?streamId=user/user-id/global.all&count=1 [status code] 401 [reason phrase] Unauthorized
Looking at the documentation page as per this line:
$response = $client->get();
It will send a get request, with no authorisation, hence the 401 response.
Try the following instead
// Create a client with a base URL.
$client = new GuzzleHttp\Client();
$request = $client-> createRequest('GET', 'cloud.feedly.com/v3/streams/contents?streamId=user/user-id/category/global.all&count=1');
$request->setHeader('Authorization', "auth-code");
// Send.
$response = $client->send($request);
dd($response->json());
The above creates a request, set the authorisation header on it. Then once prepared it actually sends it.
I think it worked in Postman because your headers are set, if you remove the authorization header it will likely fail there too.
I have not tested this but think it will work.
$response = $client->get('GET', 'cloud.feedly.com/v3/streams/contents?streamId=user/user-id/category/global.all&count=1', ['auth' => ['YOUR_USERNAME', 'YOUR_PASSWORD']]);
The 401 error means you should authenticate yourself with a valid username and password
Regards

Categories