i trying to post data as Async with using Guzzle 6(latest ver)
$client = new Client();
$request = $client->postAsync($url, [
'json' => [
'company_name' => 'update Name'
],
]);
but i am not getting any request form Guzzle like post request on terminal
Because it's a promise, you need to put then
and the promise will not called unless you put $promise->wait()
This is a simple post request using postAsync based on your question:
$client = new Client();
$promise = $client->postAsync($url, [
'json' => [
'company_name' => 'update Name'
],
])->then(
function (ResponseInterface $res){
$response = json_decode($res->getBody()->getContents());
return $response;
},
function (RequestException $e) {
$response = [];
$response->data = $e->getMessage();
return $response;
}
);
$response = $promise->wait();
echo json_encode($response);
Have you tried to send the request?
http://guzzle.readthedocs.org/en/latest/index.html?highlight=async
$client = new Client();
$request = new Request('POST', $url, [
"json" => [
'company_name' => 'update Name']
]);
$promise = $client->sendAsync($request)->then(function ($response) {
echo 'I completed! ' . $response->getBody();
});
$promise->wait();
Guzzle 6 has very little practical examples/documentation for developers to refer. I am sharing an example on how to use postAsync and Pool object. This allows concurrent async requests using guzzle 6. ( I was not able to find a direct example and spent 2 days to get working code )
function postInBulk($inputs)
{
$client = new Client([
'base_uri' => 'https://a.b.com'
]);
$headers = [
'Authorization' => 'Bearer token_from_directus_user'
];
$requests = function ($a) use ($client, $headers) {
for ($i = 0; $i < count($a); $i++) {
yield function() use ($client, $headers) {
return $client->postAsync('https://a.com/project/items/collection', [
'headers' => $headers,
'json' => [
"snippet" => "snippet",
"rank" => "1",
"status" => "published"
]
]);
};
}
};
$pool = new Pool($client, $requests($inputs),[
'concurrency' => 5,
'fulfilled' => function (Response $response, $index) {
// this is delivered each successful response
},
'rejected' => function (RequestException $reason, $index) {
// this is delivered each failed request
},
]);
$pool->promise()->wait();
}
most likely you'll need to call wait();
$request->wait();
Related
i'm working on a project where i need to perform 2000 asynchronous requests using Guzzle to an endpoint and each time i need to change the ID in the url.
the endpoint looks like this: https://jsonplaceholder.typicode.com/posts/X
I tried to use a for loop to do that the only issue is that it's not asynchronous. what's the more efficient way to do such task?
use GuzzleHttp\Client;
public function fetchPosts () {
$client = new Client();
$posts = [];
for ($i=1; $i < 2000; $i++) {
$response = $client->post('https://jsonplaceholder.typicode.com/posts/' . $i);
array_push($posts, $response->getBody());
}
return $posts;
}
You can try this,
public function fetchBooks()
{
$results = [];
$client = new \GuzzleHttp\Client([
'base_uri' => 'https://jsonplaceholder.typicode.com'
]);
$headers = [
'Content-type' => 'application/json; charset=UTF-8'
];
$requests = function () use ($client,$headers) {
for ($i = 1; $i < 7; $i++) {
yield function() use ($client, $headers,$i) {
return $client->postAsync('/posts',[
'headers' => $headers,
'json' => [
'title' => 'foonov2020',
'body' => 'barfoonov2020',
'userId' => $i,
]
]);
};
}
};
$pool = new \GuzzleHttp\Pool($client, $requests(),[
'concurrency' => 5,
'fulfilled' => function (Response $response, $index) use (&$results) {
$results[] = json_decode($response->getBody(), true);
},
'rejected' => function (\GuzzleHttp\Exception\RequestException $reason, $index) {
throw new \Exception(print_r($reason->getBody()));
},
]);
$pool->promise()->wait();
return response()->json($results);
}
It will give you output,
I want to Post data with matrix, color, and source (upload file) to an API with lumen laravel.
here my code
generateMotif(data, token) {
var path = `motif`;
var formData = new FormData();
formData.append("matrix", data.matrix);
formData.append("color", data.color);
formData.append("source", data.file);
return axios.post(`${API_URL}/${path}`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
token: token,
},
params: {
token: token,
},
})
.catch((error) => {
if (error.response) {
return Promise.reject({
message: error.response.data.error,
code: error.response.status
});
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
// The request was made but no response was received
console.log(error.request);
throw error;
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error', error.message);
// console.log(error.response.data);
throw error;
}
});
},
here my API controller code
public function generateMotif(Request $request)
{
$all_ext = implode(',', $this->image_ext);
$this->validate($request, [
'matrix' => 'required',
'color' => 'required',
'source' => 'required|file|mimes:' . $all_ext . '|max:' . $this->max_size,
]);
$model = new UserMotif();
$file = $request->file('source');
$store = Storage::put('public/upload', $file);
dd($store);
$client = new Client;
try {
$response = $client->request('POST', 'http://localhost:9000/motif', [
'multipart' => [
[
'name' => 'matrix',
'contents' => $request->input('matrix'),
'headers' => [ 'Content-Type' => 'multipart/form-data']
],
[
'name' => 'color',
'contents' => $request->input('color'),
'headers' => [ 'Content-Type' => 'multipart/form-data']
],
[
'name' => 'img_file',
// 'contents' => fopen(storage_path('app/' . $store), 'r'),
'contents' => $request->file('source'),
'filename' => $file->getClientOriginalName(),
'headers' => [ 'Content-Type' => 'multipart/form-data']
],
]
]);
$images = $data->getBody()->getContents();
$filePath = '/public/' . $this->getUserDir();
$fileName = time().'.jpeg';
if ($result = Storage::put($filePath . '/' . $fileName, $images)) {
$generated = $model::create([
'name' => $fileName,
'file_path' => $filePath,
'type' => 'motif',
'customer_id' => Auth::id()
]);
return response()->json($generated);
}
} catch (RequestException $e) {
echo $e->getRequest() . "\n";
if ($e->hasResponse()) {
echo $e->getResponse() . "\n";
}
return response($e->getResponse());
}
return response()->json(false);
}
There are no errors in my controller because I'm not found any error or issues when compiling the code. Response in my controller terminal is 200.
The results that I want from this code are an image. Because in this API, it will process an image and give new image response. But when I'm posting an image, the results are scripts like this.
{data: "<script> Sfdump = window.Sfdump || (function (doc)…re><script>Sfdump("sf-dump-1493481357")</script>↵", status: 200, statusText: "OK", headers: {…}, config: {…}, …}
I don't know what's wrong in my code, but you have any suggestion for my code, please help me. Any suggestions will be very helpful to me.
I try in postman like this :
I fill just input password. Then I click button update request
The view like this :
This is header :
This is body. I select raw and input data like this :
Then I click button send and it can get the response
But when I try use guzzle 6 like this :
public function testApi()
{
$requestContent = [
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json'
],
'json' => [
'auth' => ['', 'b0a619c152031d6ec735dabd2c6a7bf3f5faaedd'],
'ids' => ["1"]
]
];
try {
$client = new GuzzleHttpClient();
$apiRequest = $client->request('POST', 'https://myshop/api/order', $requestContent);
$response = json_decode($apiRequest->getBody());
dd($response);
} catch (RequestException $re) {
// For handling exception.
}
}
The result is empty
How can I solve this problem?
See in Postman, you correctly specify the field Authorization in the "headers" tab. So it sould be the same when you use Guzzle, put it in the headers:
public function testApi()
{
$requestContent = [
'auth' => ['username', 'password']
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'json' => [
'ids' => ["1"]
]
];
try {
$client = new GuzzleHttpClient;
$apiRequest = $client->request('POST', 'https://myshop/api/order', $requestContent);
$response = json_decode($apiRequest->getBody());
dd($response);
} catch (RequestException $re) {
// For handling exception.
}
}
I'm in a situation where I need to call the same method if any exception is thrown to ensure I'm not duplicating any code. However, it's not working as I thought. Here's the relevant code:
public static function getFolderObject($folder_id)
{
$client = new Client('https://api.box.com/{version}/folders', [
'version' => '2.0',
'request.options' => [
'headers' => [
'Authorization' => 'Bearer ' . self::getAccessToken(),
]
]
]);
$request = $client->get($folder_id);
try {
$response = $request->send();
$result = $response->json();
$files = $result['item_collection']['entries'];
} catch (BadResponseException $e) {
$result = $e->getResponse()->getStatusCode();
if ($result === 401) {
self::regenerateAccessToken();
self::getFolderObject();
}
}
return count($files) ? $files : false;
}
As you can see I'm calling the method from the method method under the if condition self::getFolderObject(); to prevent duplicate code again in under the if statement from beginning of the method. However, if I duplicate the code it works as expected. Is there any solution to achieve what I want?
You have missed to return the value and assign the folder_id:
public static function getFolderObject($folder_id)
{
$client = new Client('https://api.box.com/{version}/folders', [
'version' => '2.0',
'request.options' => [
'headers' => [
'Authorization' => 'Bearer ' . self::getAccessToken(),
]
]
]);
$request = $client->get($folder_id);
try {
$response = $request->send();
$result = $response->json();
$files = $result['item_collection']['entries'];
} catch (BadResponseException $e) {
$result = $e->getResponse()->getStatusCode();
if ($result === 401) {
self::regenerateAccessToken();
return self::getFolderObject($folder_id);
}
}
return count($files) ? $files : false;
}
I am trying to use Guzzle pool in PHP. But I am having difficulty in dealing with ASYNC request. Below is the code snippet.
$client = new \GuzzleHttp\Client();
function test()
{
$client = new \GuzzleHttp\Client();
$request = $client->createRequest('GET', 'http://l/?n=0', ['future' => true]);
$client->send($request)->then(function ($response) {
//echo 'Got a response! ' . $response;
return "\n".$response->getBody();
});
}
$res = test();
var_dump($res); // echoes null - I know why it does so but how to resolve the issue.
Does anybody how can I make function wait and get the correct result.
If you could return it it wouldn't be async in code style. Return the promise and unwrap it on the outside.
function test()
{
$client = new \GuzzleHttp\Client();
$request = $client->createRequest('GET', 'http://l/?n=0', ['future' => true]);
// note the return
return $client->send($request)->then(function ($response) {
//echo 'Got a response! ' . $response;
return "\n".$response->getBody();
});
}
test()->then(function($body){
echo $body; // access body here inside `then`
});
One other example I wanted to share using guzzle 6, postAsync and Pool.
function postInBulk($inputs)
{
$client = new Client([
'base_uri' => 'https://a.b.com'
]);
$headers = [
'Authorization' => 'Bearer token_from_directus_user'
];
$requests = function ($a) use ($client, $headers) {
for ($i = 0; $i < count($a); $i++) {
yield function() use ($client, $headers) {
return $client->postAsync('https://a.com/project/items/collection', [
'headers' => $headers,
'json' => [
"snippet" => "snippet",
"rank" => "1",
"status" => "published"
]
]);
};
}
};
$pool = new Pool($client, $requests($inputs),[
'concurrency' => 5,
'fulfilled' => function (Response $response, $index) {
// this is delivered each successful response
},
'rejected' => function (RequestException $reason, $index) {
// this is delivered each failed request
},
]);
$pool->promise()->wait();
}