0
votes

So i'm just getting started trying to understand Guzzle but one of my requests keeps returning an error, even though the exact same request when done using CURL works just fine. They look identical to me, but maybe i'm missing something about how Guzzle works. I've removed my access tokens and transaction ids for security reasons, obviously the real one I was using had the actual strings in properly. I am using the Freeagent API although I don't think which API i'm talking to has anything to do with it.

I'm sure it's a simple error stemming from me not understanding how Guzzle works, but to me this Guzzle request and Curl request look identical, so I don't understand why i'm getting an error with one and a successful request with the other.

The Guzzle request that results in an error:

$access_token = '{my_access_token_removed}';
$url = 'https://api.freeagent.com/v2/bank_transactions/{myid}';

$guzzleClient = new Client([
    'verify'    =>  false
]);

$request = $guzzleClient->get($url, array(
    'debug'     =>  true,
    'headers'   =>  array(
        'User-Agent' => 'sortitoutsi',
        'Accept' => 'application/json',
        'Content-Type' => 'application/json',
        'Authorization' => $access_token
    )
));

This CURL request works just fine:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Authorization: Bearer '.$access_token,
    'Accept: application/json',
    'Content-Type: application/json',
));
curl_setopt($ch, CURLOPT_USERAGENT, 'sortitoutsi');
curl_setopt($ch, CURLOPT_TIMEOUT, 3);

$json_response = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);

Any ideas? I've copy and pasted the entire debug info and stack trace below. I am also using Laravel, although again I can't see that being an issue.

ClientException in Middleware.php line 69: Client error: 400

in Middleware.php line 69
at Middleware::GuzzleHttp\{closure}(object(Response)) in Promise.php line 199
at Promise::callHandler('1', object(Response), array(object(Promise), object(Closure), null)) in Promise.php line 152
at Promise::GuzzleHttp\Promise\{closure}() in TaskQueue.php line 60
at TaskQueue->run() in CurlMultiHandler.php line 96
at CurlMultiHandler->tick() in CurlMultiHandler.php line 123
at CurlMultiHandler->execute(true) in Promise.php line 240
at Promise->invokeWaitFn() in Promise.php line 217
at Promise->waitIfPending() in Promise.php line 261
at Promise->invokeWaitList() in Promise.php line 219
at Promise->waitIfPending() in Promise.php line 62
at Promise->wait() in Client.php line 129
at Client->request('get', 'https://api.freeagent.com/v2/bank_transactions/{id_removed}', array('debug' => true, 'headers' => array('User-Agent' => 'sortitoutsi', 'Accept' => 'application/json', 'Content-Type' => 'application/json', 'Authorization' => '{access_token_removed}'))) in Client.php line 87
at Client->__call('get', array('https://api.freeagent.com/v2/bank_transactions/{id_removed}', array('debug' => true, 'headers' => array('User-Agent' => 'sortitoutsi', 'Accept' => 'application/json', 'Content-Type' => 'application/json', 'Authorization' => '{access_token_removed}')))) in Freeagent.php line 185
at Client->get('https://api.freeagent.com/v2/bank_transactions/{id_removed}', array('debug' => true, 'headers' => array('User-Agent' => 'sortitoutsi', 'Accept' => 'application/json', 'Content-Type' => 'application/json', 'Authorization' => '{access_token_removed}'))) in Freeagent.php line 185
at Freeagent->getTransaction('{id_removed}') in Facade.php line 210
at Facade::__callStatic('getTransaction', array('{id_removed}')) in TestingController.php line 17
at FreeagentApi::getTransaction('{id_removed}') in TestingController.php line 17
at TestingController->getTesting()
at call_user_func_array(array(object(TestingController), 'getTesting'), array()) in Controller.php line 256
at Controller->callAction('getTesting', array()) in ControllerDispatcher.php line 164
at ControllerDispatcher->call(object(TestingController), object(Route), 'getTesting') in ControllerDispatcher.php line 112
at ControllerDispatcher->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 139
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 103
at Pipeline->then(object(Closure)) in ControllerDispatcher.php line 114
at ControllerDispatcher->callWithinStack(object(TestingController), object(Route), object(Request), 'getTesting') in ControllerDispatcher.php line 69
at ControllerDispatcher->dispatch(object(Route), object(Request), 'Susie\Http\Controllers\TestingController', 'getTesting') in Route.php line 201
at Route->runWithCustomDispatcher(object(Request)) in Route.php line 134
at Route->run(object(Request)) in Router.php line 704
at Router->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 139
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 103
at Pipeline->then(object(Closure)) in Router.php line 706
at Router->runRouteWithinStack(object(Route), object(Request)) in Router.php line 671
at Router->dispatchToRoute(object(Request)) in Router.php line 631
at Router->dispatch(object(Request)) in Kernel.php line 236
at Kernel->Illuminate\Foundation\Http\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 139
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Debugbar.php line 49
at Debugbar->handle(object(Request), object(Closure))
at call_user_func_array(array(object(Debugbar), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 124
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in ActivatedUser.php line 50
at ActivatedUser->handle(object(Request), object(Closure))
at call_user_func_array(array(object(ActivatedUser), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 124
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in VerifyCsrfToken.php line 21
at VerifyCsrfToken->handle(object(Request), object(Closure))
at call_user_func_array(array(object(VerifyCsrfToken), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 124
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in ShareErrorsFromSession.php line 49
at ShareErrorsFromSession->handle(object(Request), object(Closure))
at call_user_func_array(array(object(ShareErrorsFromSession), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 124
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in StartSession.php line 62
at StartSession->handle(object(Request), object(Closure))
at call_user_func_array(array(object(StartSession), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 124
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in AddQueuedCookiesToResponse.php line 37
at AddQueuedCookiesToResponse->handle(object(Request), object(Closure))
at call_user_func_array(array(object(AddQueuedCookiesToResponse), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 124
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in EncryptCookies.php line 59
at EncryptCookies->handle(object(Request), object(Closure))
at call_user_func_array(array(object(EncryptCookies), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 124
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in CheckForMaintenanceMode.php line 42
at CheckForMaintenanceMode->handle(object(Request), object(Closure))
at call_user_func_array(array(object(CheckForMaintenanceMode), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 124
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 103
at Pipeline->then(object(Closure)) in Kernel.php line 122
at Kernel->sendRequestThroughRouter(object(Request)) in Kernel.php line 87
at Kernel->handle(object(Request)) in index.php line 53

And here's the Guzzle debug that was printed out in the browser.

* Hostname was found in DNS cache
* Hostname in DNS cache was stale, zapped
*   Trying 213.129.77.178...
* Connected to api.freeagent.com (213.129.77.178) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* Server certificate:
*    subject: C=GB; ST=City of Edinburgh; L=Edinburgh; O=FreeAgent Central Ltd.; CN=a.ssl.freeagent.com
*    start date: 2014-11-17 00:00:00 GMT
*    expire date: 2017-11-21 12:00:00 GMT
*    issuer: C=US; O=DigiCert Inc; CN=DigiCert SHA2 Secure Server CA
*    SSL certificate verify ok.
> GET /v2/bank_transactions/{id_removed} HTTP/1.1
Host: api.freeagent.com
User-Agent: sortitoutsi
Accept: application/json
Content-Type: application/json
Authorization: {access_token_removed}

< HTTP/1.1 400 Bad Request
* Server nginx is not blacklisted
< Server: nginx
< Date: Thu, 08 Oct 2015 11:14:49 GMT
< Content-Type: application/json; charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Status: 400 Bad Request
< X-Frame-Options: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< WWW-Authenticate: Bearer
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: DELETE, GET, HEAD, OPTIONS, POST, PUT
< Access-Control-Allow-Headers: Accept, Authorization, Content-Type
< Access-Control-Expose-Headers: Link
< Access-Control-Max-Age: 1728000
< Cache-Control: no-cache
< X-Request-Id: b852b734-2512-4acf-9ae0-474ad1428536
< X-Rev: 6937e9
< X-Host: web3-ash
< X-Runtime: 0.018724
< Set-Cookie: uid=1YFNslYWUCl/7GUlHLMKAg==; expires=Fri, 07-Oct-16 11:14:49 GMT; domain=.freeagent.com; path=/
< 
* Connection #0 to host api.freeagent.com left intact
1
I've not used Guzzle much, but I have Client class constructed with two parameters: a protocol+domain (api.freeagent.com) and an options array. The get() call only specifies the url without the domain. Your url is https, but the debugging says that an HTTP request was used. > GET /v2/bank_transactions/{id_removed} HTTP/1.1user2867342
I've tried it both with a base url and specifying the full url in the get with the same response and the $url definitely has https.John Mellor
Calling without the https doesn't include the server certificate at the top, which implies to me it is using httpsJohn Mellor

1 Answers

2
votes

So I figured this out myself. It was simply a human typo, it should have been:

'Authorization: Bearer '.$access_token

instead of

'Authorization: '.$access_token

The freeagent api was actually telling me this in the response, but guzzle wasn't giving me the wrong.

To get the response I simply did:

try {
    $request = $this->guzzle->request('get', $url, array(
        'debug'     =>  true,
        'headers'   =>  array(
            'User-Agent' => 'sortitoutsi',
            'Accept' => 'application/json',
            'Content-Type' => 'application/json',
            'Authorization' => 'Bearer '.$access_token
        )
    ));
} catch (ClientException $e) {
    die((string)$e->getResponse()->getBody());
}

Then I could easily see my error based on the json response from the api