Q&A: How to get POST variables with PHP on Alibaba Cloud Function Compute service

225 Views Asked by At

I played around with the PHP 7.2 runtime and HTTP trigger on Alibaba Cloud Function Compute. The basic example in the documentation is the following:

<? 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"
    );
}

This works quite well. It's easy to get the query parameters from an URL. But the body content is only available in a whole string with

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

Although the documentation says that the $request parameter follows the PSR-7 HTTP Message standard, it is not possible to use $request->getParsedBody() to deliver the values submitted by POST method. It didn't work as expected - the result remains empty.

The reason is the underlying technology. Alibaba Cloud Function Compute makes use of the event-driven React PHP library to handle the requests (you can check this by analyzing the $request object). So the $_POST array is empty and there is no "easy way to get POST data".

Luckily, Alibaba's Function Compute handler provides the body content by $request->getBody()->getContents(); as a string like

"bar=lala&foo=bar"

So a solution seems easiser than thought at the beginning, you can e.g. use PHP's own parse_str() function:

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

If you place this snippet in the handler function, the POST variables are stored in the $data array and ready for further processing.

Hope that this helps somebody who asked the same questions than I. :-)

Kind regards, Ralf

2

There are 2 best solutions below

1
On

As you can see in the documentation you need to add a RequestBodyParserMiddleware as middleware to get a parsed PSR-7 request. It seems you didn't do that.

Also keep in mind that only the Content-Types: application/x-www-form-urlencoded and multipart/form-data are supported here. So make sure the client need to send these headers so the request can be parsed. If it's another Content-Type you need to use another middleware.

See: https://github.com/reactphp/http#requestbodyparsermiddleware for more information.

I hope this helps!

0
On

@legionth: I apologize that I didn't use the comment feature here, but my answer is too long. :-) Thanks a lot for your comments - the usage of RequestBodyParserMiddleware is a great solution if you can control the server code. But in the context of Alibaba Cloud Function Compute service this seems not possible. I tried to find out more information about the invocation process - here are my results:

In server.php a React\Http\Server is started by:

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

[...]

});

[...]

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

$loop->run();

As seen in the Function Compute documentation (& example of FC console), I can only use two functions:

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

function initializer($context) {

}

and the handler function you can find in my first post.

Maybe Alibaba will extend the PHP runtime in future to make it possible to use a custom middleware, but currently I didn't find a way to do this.

Thanks again & kind regards,

Ralf