Я поиграл с исполняемой версией PHP 7.2 и триггером HTTP на Alibaba Cloud Function Compute. Основной пример в документации следующий:
<? 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
массив и готов к дальнейшей обработке.
Надеюсь, что это поможет кому-то, кто задавал те же вопросы, что и я 🙂
С уважением,
Ralf
Как вы можете видеть в документации, вам нужно добавить RequestBodyParserMiddleware
в качестве промежуточного программного обеспечения для получения проанализированного запроса PSR-7. Кажется, ты этого не делал.
Также имейте в виду, что только Content-Types: application/x-www-form-urlencoded
а также multipart/form-data
поддерживаются здесь. Поэтому убедитесь, что клиент должен отправить эти заголовки, чтобы запрос мог быть проанализирован. Если это другой тип контента, вам нужно использовать другое промежуточное ПО.
Увидеть: https://github.com/reactphp/http#requestbodyparsermiddleware для дополнительной информации.
Надеюсь, это поможет!
@legionth: Я извиняюсь, что не использовал здесь функцию комментариев, но мой ответ слишком длинный. 🙂
Большое спасибо за ваши комментарии — использование RequestBodyParserMiddleware
отличное решение, если вы можете контролировать код сервера. Но в контексте службы облачных вычислений Alibaba это кажется невозможным. Я попытался узнать больше информации о процессе вызова — вот мои результаты:
Функция Compute использует образ Docker, определенный в https://github.com/aliyun/fc-docker/blob/master/php7.2/run/Dockerfile .
В процессе сборки они загружают среду выполнения PHP из https://my-fc-testt.oss-cn-shanghai.aliyuncs.com/php7.2.tgz . (Я не нашел этого на GitHub, но код доступен для публичного скачивания.)
Сценарий оболочки start_server.sh
запускает бинарный файл PHP-CGI и запускает скрипт PHP server.php
,
В 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();
Как видно из функции Compute документация (& Пример консоли FC), я могу использовать только две функции:
/*
if you open the initializer feature, please implement the initializer function, as below:
*/
function initializer($context) {
}
и handler
функцию вы можете найти в моем первом посте.
Возможно, в будущем Alibaba расширит среду выполнения PHP, чтобы можно было использовать пользовательское промежуточное ПО, но в настоящее время я не нашел способа сделать это.
еще раз спасибо & С уважением,
Ralf