问答:如何在阿里云函数计算服务上使用PHP获取POST变量

时间:2018-11-19 20:14:47

标签: php reactphp alibaba-cloud alibaba-cloud-function-compute

我在阿里云功能计算中试用了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数组中,并准备进行进一步处理。

希望这可以帮助提出与我相同问题的人。:-)

亲切的问候,    拉尔夫

2 个答案:

答案 0 :(得分:0)

正如您在文档中所看到的,您需要添加RequestBodyParserMiddleware作为中间件来获取已解析的PSR-7请求。看来您没有那样做。

还请记住,此处仅支持内容类型:application/x-www-form-urlencodedmultipart/form-data。因此,请确保客户端需要发送这些标头,以便可以解析请求。如果是另一种Content-Type,则需要使用另一种中间件。

有关更多信息,请参见:https://github.com/reactphp/http#requestbodyparsermiddleware

我希望这会有所帮助!

答案 1 :(得分:0)

@legionth:我很抱歉在这里没有使用评论功能,但是回答太长了。 :-) 非常感谢您的评论-如果您可以控制服务器代码,则RequestBodyParserMiddleware的使用是一个很好的解决方案。但是在阿里云功能计算服务的背景下,这似乎是不可能的。我试图找出有关调用过程的更多信息-这是我的结果:

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运行时,以使其可以使用自定义中间件,但目前我还没有找到实现此目的的方法。

再次感谢您,

拉尔夫