我在阿里云功能计算中试用了PHP 7.2运行时和HTTP触发器。文档中的基本示例如下:
<? 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
参数遵循PSR-7 HTTP消息标准,但是不可能使用$request->getParsedBody()
来传递POST方法提交的值。它没有按预期工作-结果仍然为空。
原因是底层技术。阿里云功能计算利用事件驱动的React PHP库来处理请求(您可以通过分析$request
对象进行检查)。因此$_POST
数组为空,没有"easy way to get POST data"。
幸运的是,阿里巴巴的函数计算处理程序通过$request->getBody()->getContents();
以类似字符串的形式提供正文内容
"bar=lala&foo=bar"
因此,解决方案似乎比开始时想的要容易,例如使用PHP自己的parse_str()
函数:
$data = [];
$body = $request->getBody()->getContents();
parse_str($body,$data);
如果将此代码段放置在处理程序函数中,则POST变量将存储在$data
数组中,并准备进行进一步处理。
希望这可以帮助提出与我相同问题的人。:-)
亲切的问候, 拉尔夫
答案 0 :(得分:0)
正如您在文档中所看到的,您需要添加RequestBodyParserMiddleware
作为中间件来获取已解析的PSR-7请求。看来您没有那样做。
还请记住,此处仅支持内容类型:application/x-www-form-urlencoded
和multipart/form-data
。因此,请确保客户端需要发送这些标头,以便可以解析请求。如果是另一种Content-Type,则需要使用另一种中间件。
有关更多信息,请参见:https://github.com/reactphp/http#requestbodyparsermiddleware。
我希望这会有所帮助!
答案 1 :(得分:0)
@legionth:我很抱歉在这里没有使用评论功能,但是回答太长了。 :-)
非常感谢您的评论-如果您可以控制服务器代码,则RequestBodyParserMiddleware
的使用是一个很好的解决方案。但是在阿里云功能计算服务的背景下,这似乎是不可能的。我试图找出有关调用过程的更多信息-这是我的结果:
Function Compute利用https://github.com/aliyun/fc-docker/blob/master/php7.2/run/Dockerfile中定义的Docker映像。
在构建过程中,他们从https://my-fc-testt.oss-cn-shanghai.aliyuncs.com/php7.2.tgz下载PHP运行时环境。 (我没有在GitHub上找到它,但是该代码可以公共下载。)
shell脚本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();
如函数计算documentation(和FC控制台的示例)所示,我只能使用两个函数:
/*
if you open the initializer feature, please implement the initializer function, as below:
*/
function initializer($context) {
}
和handler
函数,您可以在我的第一篇文章中找到。
也许阿里巴巴将来会扩展PHP运行时,以使其可以使用自定义中间件,但目前我还没有找到实现此目的的方法。
再次感谢您,
拉尔夫