Как правильно использовать Guzzle 6 для создания пула асинхронных запросов json для отправки на конечные точки API?

Моя цель — использовать Guzzle 6 для создания пула асинхронных запрашивает данные PUT json. Затем отслеживайте каждый успех/неудача $promise.

Для сравнения с моим примером кода POOL следующий одиночный запрос к $client->request() преобразует третий параметр в закодированный json, а затем добавляет Content-type:application/json.**

$client = new Client([
    'base_uri' => BASE_URL . 'test/async/', // Base URI is used with relative requests
    'timeout'  => 0, // 0 no timeout for operations and watching Promises
]);

$response = $client->request('PUT', 'cool', ['json' => ['foo' => 'bar']]);

На принимающей конечной точке API я могу прочитать json из одного запроса выше, выполнив следующие действия:

$json = file_get_contents('php://input');
$json = json_decode($json, true);

Используя пример параллельных запросов в документации, для создания пула асинхронных запросов с помощью new Request(), я надеялся, что можно использовать те же параметры (метод, конечная точка URL, флаг json), что и в примере с одним $client->request() выше. Однако yield new Request() не обрабатывает третий параметр json, например $client->request(). Какую правильную функцию Guzzle следует вызывать из кода моего пула, чтобы правильно установить json и тип контента? Или есть лучший способ создать большой пул асинхронных запросов и отслеживать их результат?

Пример кода POOL:

$this->asyncRequests = [
    [
        'endpoint' => 'cool'
    ],
    [
        'endpoint' => 'awesome'
    ],
    [
        'endpoint' => 'crazy'
    ],
    [
        'endpoint' => 'weird'
    ]
];

$client = new Client([
    'base_uri' => BASE_URL, // Base URI is used with relative requests
    'timeout'  => 0 // 0 no timeout for operations and watching Promises
]);

$requests = function ($asyncRequests) {
    $uri = BASE_URL . 'test/async/';

    foreach ($asyncRequests as $key => $data) {
        yield new Request('PUT', "{$uri}{$data['endpoint']}", ['json' => ['foo' => 'bar']]);
    }
};

$pool = new Pool($client, $requests($this->asyncRequests), [
    'concurrency' => 10,
    'fulfilled' => function ($response, $index) {
        $this->handleSuccessPromises($response, $index);
    },
    'rejected' => function ($reason, $index) {
        $this->handleFailurePromises($reason, $index);
    },
]);

$promise = $pool->promise(); // Initiate the transfers and create a promise

$promise->wait(); // Force the pool of requests to complete.

person Zelf    schedule 07.04.2016    source источник


Ответы (2)


Надеюсь, кто-то еще подскочит и сообщит мне, есть ли более правильный способ достичь моей цели, но, заглянув под капот в Guzzle, я понял, что третий параметр нового запроса () искал информацию заголовка, а четвертый параметр искал тело. Таким образом, следующий код работает с использованием пула:

foreach ($syncRequests as $key => $headers) {
    yield new Request('PUT', "{$uri}{$headers['endpoint']}", ['Content-type' => 'application/json'], json_encode(['json' => ['nonce' => $headers['json']]]));
}

Также в документах для Psr7\Request enter

person Zelf    schedule 08.04.2016
comment
Блин, сколько времени понадобилось, чтобы понять, что body и json должны быть в 4-м параметре! Спасибо за такое понятное объяснение! - person t.mikael.d; 14.11.2016
comment
Благодарю вас! Я видел, что 3-й параметр тоже отличается, но я не знаю, что передать, хорошо, что вы указали, что вам нужно обернуть его в json_encode, вы, черт возьми, спасите меня! - person Bryan Estrito; 12.04.2018

Если вам нужен полный контроль, не используйте объект Request() в вашем пуле. Вместо этого запустите запрос самостоятельно, заставив генератор вашего пула получить вызываемую функцию, которая запускает запрос. Это дает вам полный контроль над всеми опциями. Вот правильный пример кода:

https://stackoverflow.com/a/40622269/5562035

person gw0    schedule 16.11.2016