How to convert cURL to Guzzle GET - php

First of all: First question here in Stack Overflow, quite an honor! :D
How do i convert the following curl into Guzzle?
curl -u USER_KEY:USER_SECRET https://api.apiexample.com/example/oauth/oauth?grant_type=client_credentials
I tried the following, but i kept getting 403 - Forbidden error:
$res = $client->request('GET', 'https://api.apiexample.com/example/oauth/oauth',[
'auth' => ['USER_KEY', 'USER_SECRET'],
'header' => [
'Content-Type' => 'application/x-www-form-urlencoded'
],
'form_params' => [
'grant_type' => 'client_credentials'
]
]);
What could be wrong with my code?
Edit: Forgot one thing: This request returns a token that lasts for 30 minutes. Any tip to run this function only when the token is about to expire?

I would recommend maybe reformatting your request by putting your constant values in the Client object declaration and also wrapping the request in a try-catch block. The try-catch block provides the added benefit that it will help you debug the response. Feel free to alter the catch statement as you wish.
$client = new Client([
'base_uri' => 'https://api.apiexample.com/example/',
'auth' => [
'USER_KEY',
'USER_SECRET'
]
]);
try {
$response = $client->request( 'GET', 'oauth/oauth', [
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
],
'form_params' => [
'grant_type' => 'client_credentials'
]
]);
} catch (Exception $e) {
error_log($e->getCode());
error_log($e->getMessage());
error_log(print_r($e->getTrace(), true));
}

Related

Get API response URL param using Guzzle HTTP request in Guzzle 7

I searched online but couldn't find a proper solution. I am calling a Spring service with a POST request using Guzzle Client, The service in case of any errors provides the error message in its URL param like: http://localhost:8085/fedauth/null?errMessage=Mot%20de%20passe%20invalide%20pour%20l'utilisateur%20Karan%20Sharma.. How can I fetch this param errMessage using Guzzle. Below is my code with Slim in PHP.
$data = [
'userName' => base64_encode($userName),
'userPassword' => base64_encode($userPassword),
'institution' => $institution,
'redirectUrl' => $redirectUrl,
'callerUrl' => $callerUrl,
'clientId' => $clientId,
'encryptMode' => $encryptMode,
'moodleLandPage' => $moodleLandPage,
'login' => $login,
'isEncrypted' => true
];
try {
$apiResponse = $client->post( $_ENV['FEDAUTH_API_URL'], ['form_params'=> $data]);
} catch (Exception $exception) {
return $response->write(json_encode(['error' => $exception->getMessage(), "auth" => "0" ]));
}
I have tried using the getEffectiveUrl() method but its no longer supported in Guzzle 7
I guess you get the response as a redirect url? Your question is not clear in that point. In this case you can access it like this:
$apiResponse = $client->post( $_ENV['FEDAUTH_API_URL'], ['form_params'=> $data]);
echo $apiResponse->getEffectiveUrl();
like here: https://docs.guzzlephp.org/en/5.3/http-messages.html#responses
Actually found the answer. You need to add track redirects option as true and then use $response->getHeaderLine('X-Guzzle-Redirect-History'); like below
$client = new GuzzleHttp\Client(['headers' => [ 'Content-Type' => 'application/x-www-form-urlencoded'], 'verify' => false, 'allow_redirects' => ['track_redirects' => true]]);
$apiResponse = $client->post( $_ENV['FEDAUTH_API_URL'], ['form_params'=> $data]);
echo $apiResponse->getHeaderLine('X-Guzzle-Redirect-History');

Getting API Response using Guzzle in Laravel

I am trying to get a response from the Metals API but keep getting 404 errors even though I can get the API using the URL.
public function valueFromApi(){
$accesskey = "123456";
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://metals-api.com/api/latest', [
'form_params' => [
'access_key' => $accesskey,
'base' => 'GBP',
'symbols' => 'XAU',]
]);
dd($response);
}
If I try and access the URL directly through a browser this works:
https://metals-api.com/api/latest?access_key=123456&base=GBP&symbols=XAU
I must have misunderstood the way the parameters are working. Any advice is appreciated.
Form params is not the same as query parameters. Therefor you need to set the parameters as query. If you are accessing this in the browser, i would not expect it to be a POST but a GET.
$response = $client->request('GET', 'https://metals-api.com/api/latest', [
RequestOptions::QUERY => [
'access_key' => $accesskey,
'base' => 'GBP',
'symbols' => 'XAU',
]
]);
I am using the RequestOptions, this is syntaxic sugar for the hardcoded string options, the same as 'query'.
As specified in their docs, you need to define the constant
define("form_params", GuzzleHttp\RequestOptions::FORM_PARAMS );
Then you can use your code
$response = $client->request('POST', 'https://metals-api.com/api/latest', [
'form_params' => [
'access_key' => $accesskey,
'base' => 'GBP',
'symbols' => 'XAU',]
]);

Passing client certificates through Curl request using Guzzle

I have the following curl command
sudo curl -E openyes.crt.pem --key openyes.key.pem https://sky.myapitutorial.in:444/app/live/get
which works fine. But when I am trying to do from Guzzle, its failing.
I am unable to pass the client certificates in the request.
This is what I tried
$headers = ['Content-Type' => 'application/json','X-Client-Id' => config('mykey') , 'X-Client-Secret' => config('mykey')];
$client = new client();
try {
$response = $client->post(
$endpoint
,
['json' => $content, 'headers' => $headers,['connect_timeout' => 650]],
[
'config' => [
'curl' => [
'CURLOPT_SSLKEY' => base_path().'/openyes.key.pem',
'CURLOPT_SSLCERT' => base_path().'/openyes.crt.pem',
'CURLOPT_VERBOSE' => true
],
]
],
['debug'=>true],
['http_errors' => false]
);
dd($response);
}
catch (GuzzleHttp\Exception\ClientException $e) {
$response = $e->getResponse();
throw $e;
}
I couldn't find any solution in Guzzle documentation.
Any idea why is this not working?
The error I am getting is
cURL error 35: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure (see http:\/\/curl.haxx.se\/libcurl\/c\/libcurl-errors.html)
You can use ssl_key and cert:
$response = $client->post(
$endpoint, [
'json' => $content,
'headers' => $headers,
'connect_timeout' => 650,
// add these
'cert' => '/path/to/openyes.crt.pem',
'ssl_key' => '/path/to/openyes.key.pem'
]
);
if they have a pass phrase, you can set them like this:
'cert' => ['/path/to/openyes.crt.pem', 'password'],
'ssl_key' => ['/path/to/openyes.key.pem', 'password']

Returning GuzzleHttp response object causes ERR_INVALID_CHUNKED_ENCODING in browser

I'm using guzzle 6 in laravel 5 to send a post request but I'm getting ERR_INVALID_CHUNKED_ENCODING when I try to access the request() in the method that handles the post request.
Here's my code:
Routes.php
Route::get('/guzzle', [
'as' => 'guzzle-test',
'uses' => 'TestController#getTest'
]);
Route::post('/guzzle', [
'as' => 'guzzle-post-test',
'uses' => 'TestController#postTest'
]);
TestController.php
public function getTest()
{
$client = new Client();
$data = [
'hey' => 'ho'
];
$request = $client->post(route('guzzle-post-test'), [
'content-type' => 'application/json'
], json_encode($data));
return $request;
}
public function postTest()
{
dd(getTest());
}
I getting to the post request handler since I've tried to diedump a string and it gets there, but if i call the request() I get that error. For what I've researched It may have something to with the content length, but after reading guzzle's docs and some stuff around the web I could find how to get and pass the content length appropriately in the request. Any help would be very appreciated!
First off, here's some test code which you should be able to adapt for your purposes (also see form_params in the docs for GuzzleHttp):
public function validateRecaptcha()
{
$client = new Client;
$response = $client->request('POST', 'https://www.google.com/recaptcha/api/siteverify', [
'form_params' => [
'secret' => env('RECAPTCHA_SECRET'),
'response' => Request::input('g-recaptcha-response'),
'remoteip' => Request::ip()
]
]);
return $response;
}
I just ran into the same issue and found that trying to return the response object in Laravel gave me ERR_INVALID_CHUNKED_ENCODING. Whereas, doing a dd() on the response itself showed me what I was actually wanting to see:
public function validateRecaptcha()
{
$client = new Client;
$response = $client->request('POST', 'https://www.google.com/recaptcha/api/siteverify', [
'form_params' => [
'secret' => env('RECAPTCHA_SECRET'),
'response' => Request::input('g-recaptcha-response'),
'remoteip' => Request::ip()
]
]);
dd($response);
}
Unfortunately, without doing further research, I'm unable to explain why ERR_INVALID_CHUNKED_ENCODING keeps coming up when I try to return the client library's objects to the browser, but my initial inclination is that it's a data type issue.
As far as your question goes, you're not actually trying to get back the "request" but rather the response. According to http://docs.guzzlephp.org/en/latest/quickstart.html#using-responses, if you want to get the API response contained in the response object (or at least in my case, I did), you'll want to use the getBody() method:
public function validateRecaptcha()
{
$client = new Client;
$response = $client->request('POST', 'https://www.google.com/recaptcha/api/siteverify', [
'form_params' => [
'secret' => env('RECAPTCHA_SECRET'),
'response' => Request::input('g-recaptcha-response'),
'remoteip' => Request::ip()
]
]);
return $response->getBody();
}
And then of course, if you expect it to be a JSON response (i.e. REST), then simply pass it to json_decode() to get your associative array back.
public function validateRecaptcha()
{
$client = new Client;
$response = $client->request('POST', 'https://www.google.com/recaptcha/api/siteverify', [
'form_params' => [
'secret' => env('RECAPTCHA_SECRET'),
'response' => Request::input('g-recaptcha-response'),
'remoteip' => Request::ip()
]
]);
return json_decode($response->getBody(), true); // true = assoc. array
}
Hope that helps!

Can you include raw JSON in Guzzle POST Body?

This should be soo simple but I have spent hours searching for the answer and am truly stuck. I am building a basic Laravel application and am using Guzzle to replace the CURL request I am making at the moment. All the CURL functions utilise raw JSON variables in the body.
I am trying to create a working Guzzle client but the server is respsonding with 'invalid request' and I am just wondering if something fishy is going on with the JSON I am posting. I am starting to wonder if you can not use raw JSON in the Guzzle POST request body? I know the headers are working as I am receiving a valid response from the server and I know the JSON is valid as it is currently working in a CURL request. So I am stuck :-(
Any help would be sooo greatly appreciated.
$headers = array(
'NETOAPI_KEY' => env('NETO_API_KEY'),
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'NETOAPI_ACTION' => 'GetOrder'
);
// JSON Data for API post
$GetOrder = '{
"Filter": {
"OrderID": "N10139",
"OutputSelector": [
"OrderStatus"
]
}
}';
$client = new client();
$res = $client->post(env('NETO_API_URL'), [ 'headers' => $headers ], [ 'body' => $GetOrder ]);
return $res->getBody();
You can send a regular array as JSON via the 'json' request option; this will also automatically set the right headers:
$headers = [
'NETOAPI_KEY' => env('NETO_API_KEY'),
'Accept' => 'application/json',
'NETOAPI_ACTION' => 'GetOrder'
];
$GetOrder = [
'Filter' => [
'OrderID' => 'N10139',
'OutputSelector' => ['OrderStatus'],
],
];
$client = new client();
$res = $client->post(env('NETO_API_URL'), [
'headers' => $headers,
'json' => $GetOrder,
]);
Note that Guzzle applies json_encode() without any options behind the scenes; if you need any customisation, you're advised to do some of the work yourself
$res = $client->post(env('NETO_API_URL'), [
'headers' => $headers + ['Content-Type' => 'application/json'],
'body' => json_encode($getOrders, ...),
]);
Guzzle 7 Here
The below worked for me with raw json input
$data = array(
'customer' => '89090',
'username' => 'app',
'password' => 'pwd'
);
$url = "http://someendpoint/API/Login";
$client = new \GuzzleHttp\Client();
$response = $client->post($url, [
'headers' => ['Content-Type' => 'application/json', 'Accept' => 'application/json'],
'body' => json_encode($data)
]);
print_r(json_decode($response->getBody(), true));
For some reasons until I used the json_decode on the response, the output wasn't formatted.
You probably need to set the body mime type. This can be done easily using the setBody() method.
$request = $client->post(env('NETO_API_URL'), ['headers' => $headers]);
$request->setBody($GetOrder, 'application/json');

Categories