I am using "guzzlehttp/guzzle": "~6.0", and trying to post a file to an API endpoint. The file posts fine when using RequestBin but the API is not getting the header it requires. The Header is not sent to Request bin either. According to the docs, I need to do an array of associative arrays. http://docs.guzzlephp.org/en/latest/quickstart.html#post-form-requests
However, this is not working. Here's the Guzzle request:
$client = new GuzzleHttp\Client(['base_uri' => '127.0.0.1:3000']);
$response = $client->request('POST', '/process', [
'multipart' => [
[
'name' => 'file',
'contents' => $file,
'bucketName' => 'test',
'headers' => ['X-API-Key' => 'abc345']
],
]
]);
What am I doing wrong that it's not sending the header?
Thank you very much,
Josh
Headers is an $option, that's mean it must be at the same level as multipart.
<?php
$response = $client->request('POST', '/process', [
'multipart' => [
[
'name' => 'file',
'contents' => 'test',
'bucketName' => 'test',
],
],
'headers' => ['X-API-Key' => 'abc345'] // <------- HERE
]);
You were probably using multipart in conjunction with form_params , this is not explicitly explained in the documentation of laravel but guzzle won't work with both
Note
multipart cannot be used with the form_params option. You will need to
use one or the other. Use form_params for
application/x-www-form-urlencoded requests, and multipart for
multipart/form-data requests.
This option cannot be used with body, form_params, or json
To solve this problem you will need to parse all the params to multipart, if you are using laravel or lumen you can do it in this way
if(!empty($this->files))
{
//if there is an image parse all the rest parameters to
// multipart
$file_keys=array_keys($this->files);
foreach($this->files as $k => $file)
{
$http = $http->attach($k, file_get_contents($file),$k);
}
foreach($this->data as $dk =>&$d)
{
if(!in_array($dk,$file_keys))
{
if(is_array($d))
{
$d=json_encode($d);
}
$http = $http->attach($dk,$d);
}
}
return $http=$http->post($this->url);
}
//if there isn't any file just send all as form_params
return $http=$http->post($this->url,$this->data);
Related
I have the following Postman request for testing a third party API;
What I am trying to do is convert this into code using Laravel's HTTP class, the code i currently have is;
public function uploadToThridParty()
{
$uploadContents = [
'id' => 'this-is-my-id',
'fileUpload' => true,
'frontfile' => Storage::get('somefrontfile.jpg'),
'sideview' => Storage::get('itsasideview.png'),
];
$request = Http::withHeaders(
[
'Accept' => 'application/json',
]
);
$response = $request
->asForm()
->post(
'https://urltoupload.com/upload', $uploadContents
)
}
But every time I run this, the 3rd party API comes back with Invalid ID, even though if i use Postman with the same ID it works fine.
I cant seem to figure out where i am going wrong with my code;
As #Cbroe mention about attach file before sending post request you can make this like this example:
public function uploadToThridParty()
{
$uploadContents = [
'id' => 'this-is-my-id',
'fileUpload' => true
];
$request = Http::withHeaders(
[
'Accept' => 'application/json',
]
);
$response = $request
->attach(
'frontfile', file_get_contents(storage_path('somefrontfile.jpg')), 'somefrontfile.jpg'
)
->attach(
'sideview', file_get_contents(storage_path('itsasideview.png')), 'itsasideview.jpg'
)
->post(
'https://urltoupload.com/upload', $uploadContents
)
}
Also i think you need remove asForm method because it's override your header accept type to application/x-www-form-urlencoded that is way your exception is Invalid ID
Some third party API would require you to have the request with content type as multipart/form data
you can double check all the headers being pass on your postman request HEADERS tab and view on Hidden headers.
If you indeed need your request to be in multipart/form-data, You can use the multipart options of guzzle.
Although this doesnt seem to be on Laravel HTTP-Client docs, you can simply pass a asMultipart() method in your HTTP request
just check the /vendor/laravel/framework/src/Illuminate/Support/Facades/Http.php for full reference of HTTP client.
You can have your request like this.
public function uploadToThridParty() {
$uploadContents = [
[
'name' => 'id',
'contents' => 'this-is-my-id'
],
[
'name' => 'fileUpload',
'contents' => true
],
[
'name' => 'frontfile',
'contents' => fopen( Storage::path( 'somefrontfile.jpg' ), 'r')
],
[
'name' => 'sideview',
'contents' => fopen( Storage::path( 'itsasideview.jpg' ), 'r')
],
];
$request = Http::withHeaders(['Accept' => 'application/json']);
$response = $request->asMultipart()->post('https://urltoupload.com/upload', $uploadContents );
}
I am creating a user with the api provided. I am using Laravel and trying to store data to smartrmail and docs to create new subscriber is here https://docs.smartrmail.com/en/articles/636615-list-subscribers
Each time i send request i get following error:
Server error: `POST https://go.smartrmail.com/api/v1/lists/1sptso/list_subscribers` resulted in a `500 Internal Server Error` response: {"error":"param is missing or the value is empty: subscribers"}
{"error":"param is missing or the value is empty: subscribers"}
I am using Laravel and my code is here
Route::get('smartrmail',function(){
$headers = [
'Accept' => 'application/json',
'Authorization' => 'token f91715d5-3aac-4db3-a133-4b3a9493a9a4',
'Content-Type' => 'application/json',
];
$client = new GuzzleHttp\Client([
'headers' => $headers
]);
$data = [
"subscribers"=>[
[
"email"=> "vanhalen#example.com",
"first_name"=> "van",
"last_name"=> "halen",
"subscribed"=> true,
]
]
];
$res = $client->request('POST', 'https://go.smartrmail.com/api/v1/lists/1sptso/list_subscribers', [
'form_params' => [
$data
]
]);
return($res);
// echo $res->getStatusCode();
});
Anybody help me to figure out what is wrong here. I am following this docs
https://docs.smartrmail.com/en/articles/636615-list-subscribers
to create a new subscriber
Instead of
'form_params' => [
$data
]
use
'json' => $data
Explanation
You want to send json data (I assume that because you set header 'Content-Type' => 'application/json', which means that you are sending json), but form_params is used for application/x-www-form-urlencoded.
json sets header to application/json and sends data as json.
As you set proper header, this should work too:
'body' => $data
Proper name of param you can find in Guzzle docs, I used uploading data part.
I try to send the file via GuzzleHTTP from my application to external API, I make it like this:
public function storeImagesInAmazon(Request $request) {
$uploadFilePath = 'some/endpoint';
$file = $request->file('file');
$client = new Client();
$response = $client->request('POST', $uploadFilePath, [
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'multipart/form-data',
],
'multipart' => [
[
'name' => 'file',
'contents' => $file
]
]
]);
$result = json_decode($response->getBody(), true);
return [
'hashedID' => $result['hashedID']
];
}
The error I get is:
Server error: POST some/endpoint resulted in a 500 Internal Server Error response:\n
Errorerror while processing file: Failed to process file: part was null
I tested it via Postman, adding key = 'file', value = 'some_file.pdf' in Body form-data, I am sure file is correct, I mean it isn't damaged, I tried to post different files large one, a small one, pdf or jpg/png.
But I still have this issue and I can't find a solution for this.
I found this solution Guzzle form_params not accepting array
what I'm trying to say is, you need $option as your next param like in that post
$response = $client->post('api', $options);
and that $option is where your headers or multipart or other options goes as per documentation. i already tried using $options and its worked in my case.
Does anybody know the correct way to PUT using Guzzle? my code is not working
but my post methods are working
$enrolment = $client->request('PUT', $url,[
'form_params' => [
'contactID' =>12345,
'type' =>'w'
],
'headers' => [
'apitoken' => $api_token,
'wstoken' => $ws_token
]
]);
resulted in a 500 Internal Server Error response:↵{"DATA":"","ERROR":true,"MESSAGES":"key [TYPE] doesn't exist","CODE":"0","DETAILS":""}
The PUT request does't accept form_params type as request option, so it may ignore the setting.
From Docs:
form_params
Used to send an application/x-www-form-urlencoded
POST request.
Maybe you can try using json for PUT request.
In the json part of Docs, it uses PUT as well.
$enrolment = $client->request('PUT', $url,[
'json' => [
'contactID' =>12345,
'type' =>'w'
],
'headers' => [
'apitoken' => $api_token,
'wstoken' => $ws_token
]
]);
I'm trying to delete files from my CloudFlare cache using PHP. Using Guzzle I've done this:
$client = new \GuzzleHttp\Client;
$response = $client->delete('https://api.cloudflare.com/client/v4/zones/myzoneid/purge_cache', [
'query' => [
'files' => 'https://example.com/styles.css,
],
'headers' => [
'X-Auth-Email' => 'myemail',
'X-Auth-Key' => 'myapikey',
],
]);
But when I run this I get an error:
Client error: DELETE https://api.cloudflare.com/client/v4/zones/myzoneid/purge_cache?files=https%3A%2F%2Fexample.com/etc resulted in a 400 Bad Request response: {"success":false,"errors":[{"code":1012,"message":"Request must contain one of \"purge_everything\", \"files\", \"tags\" (truncated...)
I can't get it to work using Postman either. I put in the required headers and try to set a key of files or files[] with the URL but it doesn't work. I've also tried data with raw JSON as the value like {"files":["url"]} (along with a JSON content-type header) but get the same error. It thinks I'm not sending the files key.
The method for purge_cache is POST instead of DELETE (Source: https://api.cloudflare.com/#zone-purge-files-by-url).
The payload is not sent as 'query', but as 'json'.
Files should be an array, not a string.
So the correct syntax should be....
$client = new \GuzzleHttp\Client;
$response = $client->post('https://api.cloudflare.com/client/v4/zones/myzoneid/purge_cache', [
'json' => [
'files' => ['https://example.com/styles.css'],
],
'headers' => [
'X-Auth-Email' => 'myemail',
'X-Auth-Key' => 'myapikey',
],
]);