How to post request file image data binary by PHP GuzzleHttp\Client - php

I am using an api SAFR, I am wanting to import a face image url from my AWS S3
In the documentation command curl
curl -v -X POST -H "Content-Type:application/octet-stream" -H "X-RPC-DIRECTORY: main" -H "X-RPC-AUTHORIZATION: userid:pwd" -H "XRPC-PERSON-NAME:First Last" -H "X-RPC-EXTERNAL-ID: 0000001" "https://covi.real.com/people?update=false" --data-binary #IMG_0000001.jpg
I am trying to turn it into a post request by GuzzleHttp\Client
My code:
$headers = [
'Content-Type' => 'application/octet-stream',
'X-RPC-DIRECTORY' => 'main',
'X-RPC-AUTHORIZATION' => $this->userid.':'.$this->pwd,
'XRPC-PERSON-NAME' => $this->person_name,
'X-RPC-EXTERNAL-ID' => $this->external_id,
];
$client = new Client(['headers' => $headers]);
$multipart = [
[
'name' => '0000001.jpg',
'contents' => base64_encode(file_get_contents($this->image_url)),
]
];
try {
$request = $client->post($this->endpoint, [
'query' => ['update' => 'false'],
'multipart' => $multipart,
]);
$response = $request->getBody();
return $response;
} catch (Exception $e) {
return $e;
}
But it is not correct, and returns an error:
400 Bad Request` response:↵{"message":"Content type 'multipart/form-data;boundary=6506e88515760a7c6901a4f3a42ewe2220ed1a2e6a33ae' not supported"
I have tried cURL PHP but also with no success, I don't know where I'm wrong, hope everyone help, thanks!

Silly, I found the answer in stackoverflow after posting this question
$headers = [
'X-RPC-DIRECTORY' => 'main',
'X-RPC-AUTHORIZATION' => $this->userid.':'.$this->pwd,
'XRPC-PERSON-NAME' => $this->person_name,
'X-RPC-EXTERNAL-ID' => $this->external_id,
];
$client = new Client(['headers' => $headers]);
try {
$request = $client->post($this->endpoint, [
'query' => ['update' => 'false'],
'body' => file_get_contents($this->image_url),
]);
$response = $request->getBody();
return $response;
} catch (Exception $e) {
return $e;
}

Related

Freshdesk API Create note with attachment throwing validation error

use GuzzleHttp\Client;
function insert_freshdesk_note($ticketId, $content, $attachments=null)
{
if(is_null($content)) {
return false;
}
$url = 'https://mydomain.freshdesk.com/api/v2/tickets/'.$ticketId.'/notes';
$method = 'POST';
$userName = config('freshdesk_api_key');
$password = 'password';
$data = (!empty($attachments)) ? [
"attachments[]" => $attachments,
"body" => $content,
"private" => false,
] : [
"body" => $content,
"private" => false,
];
$options = (!empty($attachments)) ? [
'json' => $data,
'auth' => [$userName, $password],
'headers' => ['content-type' => 'multipart/form-data']
] : [
'json' => $data,
'auth' => [$userName, $password]
];
$client = new Client();
try {
$response = $client->request($method, $url, $options);
return json_decode($response->getBody(), true);
} catch (Exception $e) {
Log::error($e);
}
}
Above code is working fine without attachments but when an attachment comes into the picture it's throwing the following error:-
GuzzleHttp\Exception\ClientException: Client error: `POST https://mydomain.freshdesk.com/api/v2/tickets/13033/notes` resulted in a `400 Bad Request` response:
{"description":"Validation failed","errors":[{"field":"{\"attachments","message":"Unexpected/invalid field in request","
I am working according to the documentation and I have hit a dead end as of this point. I tried other permutations and combinations but via those, I wasn't able to resolve this problem.
Can anyone please help me.
Here is the link of the documentation of freshdesk
And in $attachments[] = '#/path/to/xyz.ext' this particular is going.
The function call will go like this:-
insert_freshdesk_note($this->freshdesk_ticket_id, $noteText, $image->image_full_path);
In the above question, I was trying to achieve the addition of note using GuzzleHTTP Client, Laravel Framework, and PHP language. Here's the following source code by which it starts working.
use GuzzleHttp\Client;
function insert_freshdesk_note($ticketId, $content, $attachments=null)
{
if(is_null($content)) {
return false;
}
$url = 'https://mydomain.freshdesk.com/api/v2/tickets/'.$ticketId.'/notes';
$method = 'POST';
$userName = config('freshdesk_api_key');
$password = 'password';
$attachmentsFilePath = explode('/',$attachments);
$fileName = end($attachmentsFilePath);
$options = (!empty($attachments)) ? [
'multipart' => [
[
'name' => 'body',
'contents' => $content,
],
[
'name' => 'private',
'contents' => "false",
],
[
'name' => 'attachments[]',
'contents' => fopen($attachments, 'r'),
'filename' => $fileName,
],
],
'auth' => [$userName, $password],
] : [
'json' => [
"body" => $content,
"private" => false,
],
'auth' => [$userName, $password]
];
$client = new Client();
try {
$response = $client->request($method, $url, $options);
return json_decode($response->getBody(), true);
} catch (Exception $e) {
Log::error($e);
}
}
We have to send the data in multipart fashion in order to Freshdesk backend to understand that data is there, by writing multipart/form-type in the header won't help. If you look at documentation also with and without attachments below:-
Without Attachment:-
curl -v -u user#yourcompany.com:test -H "Content-Type: application/json" -X POST -d '{ "body":"Hi tom, Still Angry", "private":false, "notify_emails":["tom#yourcompany.com"] }' 'https://domain.freshdesk.com/api/v2/tickets/3/notes'
With Attachment:-
curl -v -u user#yourcompany.com:test -F "attachments[]=#/path/to/attachment1.ext" -F "body=Hi tom, Still Angry" -F "notify_emails[]=tom#yourcompany.com" -X POST 'https://domain.freshdesk.com/api/v2/tickets/20/notes'
The difference in the curl can be seen.
This was the missing piece that I overlooked.

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']

PHP Azure OCR - use local file

I'm using the Azure OCR Service to get the text of an image back (
https://learn.microsoft.com/de-de/azure/cognitive-services/Computer-vision/QuickStarts/PHP).
So far everything is up and running, but now I would like to use a local file instead of an already uploaded one.
$url->setQueryVariables($parameters);
$request->setMethod(HTTP_Request2::METHOD_POST);
// Request body
$request->setBody("{body}"); // Replace with the body, for example, "{"url": "http://www.example.com/images/image.jpg"}
Unfortunately I don't know how to pass the raw binary as the body of my POST request in PHP.
At first, when we refer local file, we should use 'Content-Type': 'application/octet-stream' in a header, then we can send requests that use a stream resource as the body.
Here's my working code using Guzzle for your reference:
<?php
require 'vendor/autoload.php';
$resource = fopen('./Shaki_waterfall.jpg', 'r');
$client = new \GuzzleHttp\Client();
$res = $client->request('POST', 'https://westus.api.cognitive.microsoft.com/vision/v1.0/analyze', [
'query' => [
'visualFeatures' => 'Categories',
'details' => '',
'language' => 'en'
],
'headers' => [
'Content-Type' => 'application/octet-stream',
'Ocp-Apim-Subscription-Key' => '<Ocp-Apim-Subscription-Key>'
],
'body' => $resource
]);
echo $res->getBody();
Using HTTP_Request2:
<?php
require_once 'HTTP/Request2.php';
$request = new Http_Request2('https://westus.api.cognitive.microsoft.com/vision/v1.0/analyze');
$url = $request->getUrl();
$headers = array(
'Content-Type' => 'application/octet-stream',
'Ocp-Apim-Subscription-Key' => '<Ocp-Apim-Subscription-Key>',
);
$request->setHeader($headers);
$parameters = array(
'visualFeatures' => 'Categories',
'details' => '',
'language' => 'en',
);
$url->setQueryVariables($parameters);
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setBody(fopen('./Shaki_waterfall.jpg', 'r'));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}

(Updated) Laravel PUT Method Not Working

updated - the JSON file would return but it will not change the billing date at all.
Reference 1: The official documentation about changing the billing date.
Reference2: their sample code in detail:
<?php
$request = new HttpRequest();
$request->setUrl('https://domain.chargify.com/subscriptions/$subscriptionId.json');
$request->setMethod(HTTP_METH_PUT);
$request->setHeaders(array(
'authorization' => 'Basic YXBpa2V5Og==',
'content-type' => 'application/json'
));
$request->setBody('{"subscription":{"next_billing_at":"2028-12-15"}}');
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
My code in detail:
public function changeYearlySubscriptionBillingDate(Request $request)
{
$user = $request->user();
$subscriptionId = $user->subscription->subscription_id;
$nextBilling = Carbon::now()->addYear();
$hostname = env('CHARGIFY_HOSTNAME');
$headers = [
'authorization' => 'Basic ANIDIANDIAJIJCQ',
'content-type' => 'application/json'
];
$body = ["subscription" => ["next_billing_at" =>[ $nextBilling ]]];
$config = [
'headers' => $headers,
'form_param' => $body
];
$client = new Client($config);
$res = $client->put("https://$hostname/subscriptions/$subscriptionId.json",
["json" => [
[ "subscription" =>
[ "next_billing_at" => $nextBilling ]
]
]
]);
echo $res->getBody();
}
The url you are building is incorrect. There shouldn't be a / between $subscription and .json
Change
$res = $client->put("https://$hostname/subscriptions/$subscriptionId/.json",
to
$res = $client->put("https://$hostname/subscriptions/$subscriptionId.json",
EDIT
Try changing the logic to make Guzzle call like this.
$headers = [
'authorization' => 'Basic ANIDIANDIAJIJCQ',
'content-type' => 'application/json'
];
$body = ["subscription" => ["next_billing_at" =>[ $nextBilling ]]];
$client = new Client();
$res = $client->put("https://$hostname/subscriptions/$subscriptionId.json",
[
'headers' => $headers,
'body' => json_encode($body)
]
);
echo $res->getBody()->getContents();
thanks everyone so much for helping me out.
I've been working on this problem for 2 days and it was supposed to be right to me. Eventually, it is their API that misled me.
the only thing we need to do, is simply change
'body' => "{\"subscription\":{\"next_billing_at\":\"$nextBilling\"}}"
added a few '\' s inside.
Thanks everyone for helping me out, have a good day!

Guzzle PUT request auth error

I have the following code to save content using API from another system. I have added the credentials but it showing wrong credentials error. It is working perfectly in postman.
$client = new GuzzleHttpClient();
try {
$request = new \GuzzleHttp\Psr7\Request('PUT', config('cms.api.backend') .'/products/'. $nid,
[
'auth' => [config('cms.api.user'), config('cms.api.password')],
'form_params' => [
'copywrite' => Input::get('copywrite'),
'status' => $status
],
]);
$promise = $client->sendAsync($request)->then(function ($response) {});
$promise->wait();
}
catch (RequestException $e) {
$this->logHttpError($e->getResponse()->getStatusCode(), $e->getResponse()->getBody(true));
}
What could be wrong in the above code?
Following is the exported code from postman.
$request = new HttpRequest();
$request->setUrl('http://mybackend/api/products/74371');
$request->setMethod(HTTP_METH_PUT);
$request->setHeaders(array(
'postman-token' => 'e0ddcaea-4787-b2c5-0c52-9aaee860ceac',
'cache-control' => 'no-cache',
'authorization' => 'Basic authenticationcode',
'content-type' => 'application/x-www-form-urlencoded'
));
$request->setContentType('application/x-www-form-urlencoded');
$request->setPostFields(array(
'copywrite' => 'date to be saved'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
Third argument in \GuzzleHttp\Psr7\Request is for headers array only, so you won't send request body (4th arg) this way. Easiest way would be passing this array as second argument to sendAsync() method. It will recognise them and form_params option will be parsed as Content-Type: application/x-www-form-urlencoded header and create a valid stream for your request (it uses http_build_query() function if you want to do it directly in request constructor):
$request = new \GuzzleHttp\Psr7\Request('PUT', config('cms.api.backend') .'/products/'. $nid);
$options = [
'auth' => [config('cms.api.user'), config('cms.api.password')],
'form_params' => [
'copywrite' => Input::get('copywrite'),
'status' => $status
],
];
$promise = $client->sendAsync($request, $options)->then(function ($response) {});
$promise->wait();

Categories