Q&A: Как получить переменные POST с помощью PHP на сервисе облачных функций Alibaba Cloud Function

Я играл с PHP 7.2 и триггером HTTP в облачной функции Alibaba. Основной пример в документации следующий:

<? php
use RingCentral\Psr7\Response;
function handler($request, $context): Response{
    /*
    $body       = $request->getBody()->getContents();
    $queries    = $request->getQueryParams();
    $method     = $request->getMethod();
    $headers    = $request->getHeaders();
    $path       = $request->getAttribute("path");
    $requestURI = $request->getAttribute("requestURI");
    $clientIP   = $request->getAttribute("clientIP");
    */
    return new Response(
        200,
        array(
            "custom_header1" => "v1"            
        ),
        "hello world"
    );
}

Это работает довольно хорошо. Легко получить параметры запроса из URL. Но содержание тела доступно только во всей строке с

$request->getBody()->getContents();

Хотя в документации сказано, что $request параметр соответствует стандарту HTTP-сообщения PSR-7, его невозможно использовать $request->getParsedBody() доставить значения, представленные методом POST. Это не сработало, как ожидалось - результат остается пустым.

Причина в базовой технологии. Cloud Function Compute в Alibaba использует управляемую событиями библиотеку React PHP для обработки запросов (это можно проверить, проанализировав $request объект). Итак $_POST массив пуст и нет "простого способа получить данные POST".

К счастью, обработчик функций Alibaba Function Compute предоставляет содержимое тела $request->getBody()->getContents(); как строка

"bar=lala&foo=bar"

Таким образом, решение кажется проще, чем предполагалось в начале, вы можете, например, использовать собственный PHP parse_str() функция:

$data = [];
$body = $request->getBody()->getContents();
parse_str($body,$data);

Если вы поместите этот фрагмент в функцию-обработчик, переменные POST будут сохранены в $data массив и готов к дальнейшей обработке.

Надеюсь, что это поможет кому-то, кто задавал те же вопросы, что и я:-)

С уважением, Ральф

2 ответа

Как вы можете видеть в документации, вам нужно добавить RequestBodyParserMiddleware в качестве промежуточного программного обеспечения для получения проанализированного запроса PSR-7. Кажется, ты этого не делал.

Также имейте в виду, что только Content-Types: application/x-www-form-urlencoded а также multipart/form-data поддерживаются здесь. Поэтому убедитесь, что клиент должен отправить эти заголовки, чтобы запрос мог быть проанализирован. Если это другой тип контента, вам нужно использовать другое промежуточное ПО.

Смотрите: https://github.com/reactphp/http для получения дополнительной информации.

Надеюсь, это поможет!

@legionth: я извиняюсь, что не использовал здесь функцию комментариев, но мой ответ слишком длинный.:-) Большое спасибо за ваши комментарии - использование RequestBodyParserMiddleware отличное решение, если вы можете контролировать код сервера. Но в контексте сервиса облачных функций Alibaba это кажется невозможным. Я попытался узнать больше информации о процессе вызова - вот мои результаты:

В server.php React\Http\Server запускается:

$server = new Server(function (ServerRequestInterface $request) {

[...]

});

[...]

$socket = new \React\Socket\Server(sprintf('0.0.0.0:%s', $port), $loop);
$server->listen($socket);

$loop->run();

Как видно из документации по функциональным вычислениям (& пример консоли FC), я могу использовать только две функции:

/*
if you open the initializer feature, please implement the initializer function, as below:
*/

function initializer($context) {

}

и handler функцию вы можете найти в моем первом посте.

Возможно, в будущем Alibaba расширит среду выполнения PHP, чтобы можно было использовать пользовательское промежуточное ПО, но в настоящее время я не нашел способа сделать это.

Еще раз спасибо и всего наилучшего,

Ralf

Другие вопросы по тегам