I am sending a POST request to an API, Curl returns 200 and the correct response.
When Implementing with GuzzleHttp\Client, I get a 400 Bad request, what is wrong with my formatting.
here is my code using Laravel Returns 400 Bad Request:
$client = new Client();
$URI = 'http://api.example.com';
$params['headers'] = ['Content-Type' => 'application/json',
'apikey' => config('app._api_key'),
'debug' => true
];
$params['form_params'] = [
'sender' => 'Test_sender',
'recipient' => config('app.test_recipient'),
'message_body' => 'Test body'
];
return $response = $client->post($URI, $params);
Curl (Returns 200):
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'apikey: 212121212’ -d '{ "message_body": "test","sender": "2018","recipient": “4453424141” }' 'http://api.example.com'
Try the below code:
$client = new \GuzzleHttp\Client(['headers' => ['Content-Type' => 'application/json',
'apikey'=> config('app._api_key'),
'debug' => true
]
]);
$URI = 'http://api.example.com';
$body['sender']='Test_sender';
$body['recipient']=config('app.test_recipient');
$body['message_body']='Test body';
$body=json_encode($body);
$URI_Response = $client->request('POST',$URI,['body'=>$body]);
$URI_Response =json_decode($URI_Response->getBody(), true);
return $URI_Response;
Note: I would suggest you to handle error please refer GuzzleDocumentation
That is proper error handling:
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
try {
$response = $client->get(YOUR_URL, [
'connect_timeout' => 10
]);
// Here the code for successful request
} catch (RequestException $e) {
// Catch all 4XX errors
// To catch exactly error 400 use
if ($e->getResponse()->getStatusCode() == '400') {
echo "Got response 400";
}
// You can check for whatever error status code you need
} catch (\Exception $e) {
// There was another exception.
}
Implementation: http://guzzle.readthedocs.org/en/latest/quickstart.html
You can handle errors like this
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\RequestException;
use Exception;
try{
$client = new Client();
$response = $client->request('POST', $url,[
'headers' => $header,
'form_params' => $form-params
]);
$body = $response->getBody();
$status = 'true';
$message = 'Data found!';
$data = json_decode($body);
}catch(ClientException $ce){
$status = 'false';
$message = $ce->getMessage();
$data = [];
}catch(RequestException $re){
$status = 'false';
$message = $re->getMessage();
$data = [];
}catch(Exception $e){
$this->status = 'false';
$this->message = $e->getMessage();
$data = [];
}
return ['status'=>$status,'message'=>$message,'data'=>$data];
Related
I use Guzzle to send messages to the Slack API. It's all working fine except for the warning missing-charset. Here is my Guzzle function:
private function guzzleClient(string $method, string $url, array $parameters = [])
{
$client = new Client(['headers' => [
'Authorization' => "Bearer " . $this->slackOauthToken,
'Content-Type' => 'application/json; charset=utf-8',
]]);
switch (strtoupper($method)) {
case "POST":
$response = $client->post($url, [RequestOptions::JSON => $parameters]);
break;
case "GET":
$response = $client->get($url, ["query" => $parameters]);
break;
}
$json = json_decode($response->getBody()->getContents());
if((is_object($json)) && ($json->ok == false)) {
return "Error: " . $json->error . "\n";
} else {
return $json;
}
}
As far as I can determine, the charset is there and in the headers. But I keep still getting the missing-chaset error - where am I going wrong?
I've tried several methods to download an mp3 file via API get request. I feel like as if I'm close but just can't seem to get the download.
My URL returns a binary mp3 file.
This is a portion of what I'm getting in my response header array returning with the get request. Hope this is helpful.
"Content-Disposition" => array:1 [
0 => "attachment; filename=RE3e327a2615b93f528fee111da9b60e17.mp3; filename*=UTF-8''sample.mp3"
]
Here is a sample of my code using the Guzzle client in Laravel. Trying Laravel's download method but I believe I need to get the actual file from the Content-Disposition. Much appreciated for any help. Thanks.
$client = new Client();
try {
$url = 'http://getmp3website.net/recording/sample.mp3';
$response = $client->request('GET', $url,
[
'headers' => [
'Authorization' => 'bearer ' . env("AUTH_TOKEN"),
'Content-Type' => 'audio/mp3',
],
]);
return response()->download($response);
} catch (Exception $ex) {
return $ex;
}
#Note: this is not a tested answer, I have just provided an example to follow the comments above
<?php
$client = new Client();
try {
$url = 'http://getmp3website.net/recording/sample.mp3';
$resource = \GuzzleHttp\Psr7\Utils::tryFopen('/path/to/file', 'w');
//or you can use $myFile = fopen('/path/to/file', 'w') or die('not working');
$stream = \GuzzleHttp\Psr7\Utils::streamFor($resource);
$client->request('GET', $url , [
'save_to' => $stream,
'headers' => [
'Authorization' => 'bearer ' . env("AUTH_TOKEN"),
'Content-Type' => 'audio/mp3',
],
]
);
/**
* // As `save_to` is deprecated(guzzle wants us to download files as stream I guess), you can use sink as well, sink will automatically stream files for you
$resource = \GuzzleHttp\Psr7\Utils::tryFopen('/path/to/file', 'w');
$client->request('GET', $url, ['sink' => $resource]);
*/
return response()->download($pathsavedfile);
} catch(\GuzzleHttp\Exception\RequestException $e){
// you can catch here 400 response errors and 500 response errors
// You can either use logs here
$error['error'] = $e->getMessage();
$error['request'] = $e->getRequest();
if($e->hasResponse()){
if ($e->getResponse()->getStatusCode() == '400'){
$error['response'] = $e->getResponse();
}
}
Log::info('Error occurred in request.', ['error' => $error]);
}catch (Exception $ex) {
return $ex;
}
I'm learning to use an API. They provide an example of the following authentication code:
curl -X POST --header "Content-Type: application/json" --header "Accept: application/json" -d " {\"Username\": \"the_username\",
\"Password\": \"the_password\"}
" "https://someurl.someapi.com:443/api/Login/Authenticate"
However I need to reproduce this with a Guzzle request. Here is what I've been trying
$headers = [
"Content-Type" => "application/json",
"Accept" => 'application/json -d " {\"Username\": \"the_username\", \"Password\": \"the_password\" }" ',
];
// $headers = [
// "Content-Type" => "application/json"
// ];
$extra_data = ["proxy" => $proxy,
"headers" => $headers ];
// Defining the Guzzle Client to communicate with Legacy.com
$client = new Client([
// Base URI is used with relative requests
'base_uri' => 'https://someurl.someapi.com:443/api/Login/Authenticate',
// You can set any number of default request options.
'timeout' => 10.0,
]);
try {
$response = $client->request('POST', '', $extra_data);
}
However no matter what I try (this was the latest of my failed attempts), I can't get anything other than a code 400 error.
So I finally figured how to do this:
This code worked!
$str = json_decode('{ "Username": "' . $username . '", "Password": "' . $password . '"}',true);
var_dump($str);
if ($str == NULL) return;
$url_authenticate = "Login/Authenticate";
$extra_data = ["proxy" => $proxy,
"json" => $str ];
// Defining the Guzzle Client to communicate with Legacy.com
$client = new Client([
// Base URI is used with relative requests
'base_uri' => 'https://someurl.someapi.com:443/api/',
// You can set any number of default request options.
'timeout' => 10.0,
]);
try {
$response = $client->request('POST', $url_authenticate, $extra_data);
}
catch (Exception $e) {
echo 'Exception: ' . $e->getResponse()->getStatusCode() . "\n";
exit;
}
$body = $response->getBody();
echo $body;
The key was use the json field int the extra data and transform the json to php array using json_decode. I hope this helps someone else
This function is meant to download .zip files
function download($url, $debug = false)
{
$client = new Client([
'connect_timeout' => 10,
'timeout' => 60.0,
'debug' => $debug
]);
$response = $client->request('GET', $url);
try {
if ($response->getStatusCode() == 200) {
return $response->getBody()->getContents();
}
} catch (RequestException $e) {
//var_dump($response->getBody()->getContents());
$txt = json_encode(['log_error' => $e->getResponse(), 'response' => $response->getBody()->getContents(), 'url' => $url]);
file_put_contents(storage_path() . '/logs-etiquetas/log-' . microtime(true) . '-' . auth()->user()->company_id . '.txt', $txt);
}
return false;
}
I'm getting error below
production_ERROR: Client error: GET https: //api.mercadolibre.com/shipment_labels? shipment_ids = 27868452659,27864682043,27168438675,27868264704,27868866716,27868738288,27867965828 & response_type = zpl2 & caller.id = 23264143 & access_token = 400 Bad Request response:
bad_request
I've tried using Guzzle's docs to set proxy but it's not working. The official Github page for Goutte is pretty dead so can't find anything there.
Anyone know how to set a proxy?
This is what I've tried:
$client = new Client();
$client->setHeader('User-Agent', $user_agent);
$crawler = $client->request('GET', $request, ['proxy' => $proxy]);
I have solved this problem =>
$url = 'https://api.myip.com';
$client = new \Goutte\Client;
$client->setClient(new \GuzzleHttp\Client(['proxy' => 'http://xx.xx.xx.xx:8080']));
$get_html = $client->request('GET', $url)->html();
var_dump($get_html);
You thinking rigth, but in Goutte\Client::doRequest(), when create Guzzle client
$guzzleRequest = $this->getClient()->createRequest(
$request->getMethod(),
$request->getUri(),
$headers,
$body
);
options are not passed when create request object. So, if you want to use a proxy, then override the class Goutte\Client, the method doRequest(), and replace this code on
$guzzleRequest = $this->getClient()->createRequest(
$request->getMethod(),
$request->getUri(),
$headers,
$body,
$request->getParameters()
);
Example overriding class:
<?php
namespace igancev\override;
class Client extends \Goutte\Client
{
protected function doRequest($request)
{
$headers = array();
foreach ($request->getServer() as $key => $val) {
$key = implode('-', array_map('ucfirst', explode('-', strtolower(str_replace(array('_', 'HTTP-'), array('-', ''), $key)))));
if (!isset($headers[$key])) {
$headers[$key] = $val;
}
}
$body = null;
if (!in_array($request->getMethod(), array('GET','HEAD'))) {
if (null !== $request->getContent()) {
$body = $request->getContent();
} else {
$body = $request->getParameters();
}
}
$guzzleRequest = $this->getClient()->createRequest(
$request->getMethod(),
$request->getUri(),
$headers,
$body,
$request->getParameters()
);
foreach ($this->headers as $name => $value) {
$guzzleRequest->setHeader($name, $value);
}
if ($this->auth !== null) {
$guzzleRequest->setAuth(
$this->auth['user'],
$this->auth['password'],
$this->auth['type']
);
}
foreach ($this->getCookieJar()->allRawValues($request->getUri()) as $name => $value) {
$guzzleRequest->addCookie($name, $value);
}
if ('POST' == $request->getMethod() || 'PUT' == $request->getMethod()) {
$this->addPostFiles($guzzleRequest, $request->getFiles());
}
$guzzleRequest->getParams()->set('redirect.disable', true);
$curlOptions = $guzzleRequest->getCurlOptions();
if (!$curlOptions->hasKey(CURLOPT_TIMEOUT)) {
$curlOptions->set(CURLOPT_TIMEOUT, 30);
}
// Let BrowserKit handle redirects
try {
$response = $guzzleRequest->send();
} catch (CurlException $e) {
if (!strpos($e->getMessage(), 'redirects')) {
throw $e;
}
$response = $e->getResponse();
} catch (BadResponseException $e) {
$response = $e->getResponse();
}
return $this->createResponse($response);
}
}
And try send request
$client = new \igancev\override\Client();
$proxy = 'http://149.56.85.17:8080'; // free proxy example
$crawler = $client->request('GET', $request, ['proxy' => $proxy]);
You can directly use in Goutte or Guzzle Request
$proxy = 'xx.xx.xx.xx:xxxx';
$goutte = new GoutteClient();
echo $goutte->request('GET', 'https://example.com/', ['proxy' => $proxy])->html();
Use Same method in Guzzle
$Guzzle = new Client();
$GuzzleResponse = $Guzzle->request('GET', 'https://example.com/', ['proxy' => $proxy]);
You can set a custom GuzzleClient and assign it to Goutte client.
When Guzzle makes the request through Goutte uses the default config. That config is passed in the Guzzle construct.
$guzzle = new \GuzzleHttp\Client(['proxy' => 'http://192.168.1.1:8080']);
$goutte = new \Goutte\Client();
$goutte->setClient($guzzle);
$crawler = $goutte->request($method, $url);
For recent versions use:
Goutte Client instance (which extends Symfony\Component\BrowserKit\HttpBrowser)
use Symfony\Component\HttpClient\HttpClient;
use Goutte\Client;
$client = new Client(HttpClient::create(['proxy' => 'http://xx.xx.xx.xx:80']));
...