form_params method get guzzle php - laravel

I have an API get list user. postmen
and Headers Content-Type = application/json
- In laravel, I use guzzle to call api
code demo:
$client = new Client();
$headers = ['Content-Type' => 'application/json'];
$body = [
'json' => [
"filter" => "{}",
"skip" => 0,
"limit" => 20,
"sort" => "{\"createAt\": 1}",
"select" => "fullname username",
"populate" => "'right', 'group'",
]
];
\Debugbar::info($body);
$response = $client->get('http://sa-vn.com:2020/api/users/user', [
'form_params' => $body
]);
echo $response->getBody();
But it does not working! please help me

form_params and body both are different params in guzzle. check json
$json = [
"filter" => json_encode((object)[]),
"skip" => 0,
"limit" => 20,
"sort" => json_encode((object)['createAt'=>1]),
"select" => "fullname username",
"populate" => "'right', 'group'"
];
$response = $client->request('get', 'http://sa-vn.com:2020/api/users/user', [
'json' => $json,
]);
If any error occur try without json_encode as well.
$json = [
"filter" => (object)[],
"skip" => 0,
"limit" => 20,
"sort" => (object)['createAt'=>1],
"select" => "fullname username",
"populate" => "'right', 'group'"
];

As per Guzzle doucmentation
form_params
Used to send an application/x-www-form-urlencoded POST request.
json
The json option is used to easily upload JSON encoded data as the body of a request. A Content-Type header of application/json will be added if no Content-Type header is already present on the message.
You are passing json data in postman. So you can use json instead of form_params
Change
$response = $client->get('http://sa-vn.com:2020/api/users/user', [
'form_params' => $body
]);
to
$response = $client->get('http://sa-vn.com:2020/api/users/user', [
'json' => $body
]);

Related

Laravel 9 | cURL request to HTTP Client

New versions of laravel have their own HTTP client. I like the syntax and want to use it. Before that I was always using cURL.
I am now trying to make a request with the new HTTP client, but I always get a weird result back. Status is 200 btw.:
{
"cookies": {},
"transferStats": {}
}
I dont know where this comes from, my endpoint does not return this.
This is the cURL version, which works:
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => env('SCAMMER_CHECK_ENDPOINT'),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => array('auth' => $data['auth'],'authUserId' => $msd_user_id,'img' => $data['base64img']),
));
$scammer_check = curl_exec($curl);
curl_close($curl);
This is the same request with the HTTP client, which does not work:
$scammer_check = Http::post(env('SCAMMER_CHECK_ENDPOINT'), [
'auth' => $data['auth'],
'authUserId' => $msd_user_id,
'img' => $data['base64img']
]);
I also tried to use raw body, but same result:
$scammer_check = Http::withBody(
json_encode(array('auth' => $data['auth'],'authUserId' => $msd_user_id,'img' => $data['base64img'])), 'application/json'
)->post(env('SCAMMER_CHECK_ENDPOINT'));
It seems like the HTTP client is returning an empty response with cookies and transferStats. This could be due to incorrect response handling.
You could try retrieving the response body by using the "body" method on the response object like this:
$response = Http::post(env('SCAMMER_CHECK_ENDPOINT'), [
'auth' => $data['auth'],
'authUserId' => $msd_user_id,
'img' => $data['base64img']
]);
$scammer_check = $response->body();
Alternatively, you could try specifying the expected response format like this:
$scammer_check = Http::post(env('SCAMMER_CHECK_ENDPOINT'), [
'auth' => $data['auth'],
'authUserId' => $msd_user_id,
'img' => $data['base64img']
])->json();

How to run GRAPHQL query using laravel lumen suing concurrent request

i'm running graphql query through array in Laravel postAsyn. any solution for that. below i added graphql query.
$client = new Client([
// Base URI is used with relative requests
'base_uri' => $url,
// You can set any number of default request options.
'timeout' => 300.0,
]);
foreach($arr as $value){
$graphQLquery = '{'.
'"query": "query viewer {'.
'repositories(last: '. $value . ') {'.
'nodes {'.
'name'.
'id'.
'isPrivate'.
'nameWithOwner'.
'}'.
'}'.
'}",'.
'"variables": { "name": "'.$name.'", "id": "1", "isPrivate ": "True", "nameWithOwner": "VimDiesel"}'.
'}';'
}
$params = [
'query' => [
'access_token' => $token,
'query' => $query[0]
]
];
$promises = [
'image' => $client->postAsync('POST', 'graphql', json_encode($params))
];
$responses = Promise\Utils::unwrap($promises);
if anyone have solution for that please add. i need run this all queries concurrent processing. i'm using guzzelhttp.

Error: Pass content as json or plain text

I am using guzzle to post data to the api as below. When i post, the api returns Error: Pass content as json or plain text. Is it possible to convert content to JSON or Plain Text in the code below
How can I resolve this?
Controller
$headers = [
'Content-Type' => 'application/x-www-form-urlencoded',
];
$client = new \GuzzleHttp\Client([
'headers' => $headers
]);
$body = '{
"item" : Summer-Jacket,
"content" : Hi
}';
$url = "https://api.com";
$request = $client->post($url,
[
'body' => $body
] );
$response = $request->send();
Firstly your body is not even valid JSON. Strings needs to have "string" around them
To post JSON with guzzle, you can instead use the RequestOptions for exactly that.
$result = $client->post("https://api.com", [
RequestOptions::JSON => [
'item' => 'Summer-Jacket',
'content' => 'hi',
]
)->getBody();

File upload corruption

Im trying to upload a file to sharepoint
Successful try with just axios is the following
Failure if i upload using Guzzle
Uploaded file at the end is corrupted
There are a few things you need to modify to get this working (tested on my end):
To get the contents of the file, you need $request->file('file') and then use file_get_contents() on it. You can lose the get() part.
Make sure you're sending the header to accept multipart/form-data too:
"Accept" => "multipart/form-data"
Fields name and filename in a form are two different things. Former is the name of the field while the latter is the name of the file. You need to send both.
Try this:
protected function uploadFile(Request $request){
$file = $request->file('file');
$body = [
"headers" => [
"Accept" => "multipart/form-data",
"Authorization" => "Bearer {$this->token}"
],
"multipart" => [
"name" => "file",
"contents" => file_get_contents($file),
"filename" => $file->getClientOriginalName()
]
];
return (new Client)->request('POST', 'https://.sharepoint.com/...', $body);
}
P.S. - You can check whether a file is valid or not using isValid():
if ($request->file('file')->isValid()) {
//
}
Official docs on this: https://laravel.com/docs/7.x/requests#retrieving-uploaded-files
When providing content to be uploaded to Guzzle client as string,
Guzzle tries to infer necessary information about the file such as filename, content-type.
You can help Guzzle to infer these information correctly to build the multipart request by passing information about about the filename and content-type in the multipart payload.
[
//...
'multipart' => [
[
'name' => 'fileName',
'contents' => $request->file('file')->get(),
'filename' => $request->file('file')->getName(),
'headers' => [
'content-type' => $request->file('file')->getMimeType(),
]
]
]
]
Add content-type as blob.
axios.post(
'https://sharepoint....'
,data.get('file')
{
'headers' {
'Authorization': `Bearer ${this.token}`
,'Content-Type': 'blob',
}
}
)
Try something like this.
Remove the ->get() of your $request->file()
//Get the file object from the request.
$file = $request->file('file');
//Make the request
return (new Client)->request('POST', 'https://.sharepoint.com/sites....', [
'headers' => [ 'Authorization' => "Bearer {$this->token}" ],
'multipart' => [
[
'name' => 'FileContents',
'contents' => $file,
'filename' => $file->getClientOriginalName()
],
],
]);
In my opinion, you should store it somewhere in your local server temporarily first, and then you sent that file to sharepoint, deleted the temporary file, I think if you send it right away without storing it, the file will be corrupted. Please try the way below
$file = $request->file('logo');
$original_name = $file->getClientOriginalName(); // get original file
$name = time() . '_' . $original_name; // store it in different name so it would not be duplicated
$path = base_path() .'/public_html/your_project/public/temporary/'; // full path of file folder
// store the uploaded file
$file->move($path, $name);
$body = [
"headers" => [
"Authorization" => "Bearer {$this->token}"
],
"multipart" => [
"name" => "logo",
"contents" => fopen($path . $name, 'r')
]
];
$response = (new Client)->request('POST', 'https://.sharepoint.com/...', $body);
// remove the file after done
unlink($path . $name);
return $response;
Hope this would work for you! Please correct me if I was wrong

Laravel 7 HTTP Client - Unable to send POST request with `body`

Using Laravel 7.6 and it's built-in HTTP Client.
I'm trying to send a simple POST request with body in Raw JSON format to my other domain but no luck:
$response = Http::post('https://example.com', [
'body' => '{ test: 1 }'
]);
I get 400 Bad Request - Client error - because my server expects body as a mandatory.
What am I missing here?
$response = Http:post('http://example.com/', [
'foo' => 'bar'
]);
Or this
$response = Http::withHeaders([
'User-Agent' => 'Some Agent',
])->asForm()->post('http://www.example.com/', [
'foo' => 'bar',
]);
Try this, in my case this should works.
$response = Http::withHeaders(['Content-Type' => 'application/json'])
->send('POST', 'https://example.com', [
'body' => '{ test: 1 }'
])->json();

Resources