简体   繁体   English

在 aws lambda 中执行 php

[英]Execute php in aws lambda

I have two files: index.js and php-cgi我有两个文件:index.js 和 php-cgi

When I press the test button in aws lambda console I see an empty string instead of the php version.当我在 aws lambda 控制台中按下测试按钮时,我看到一个空字符串而不是 php 版本。

Here is my Index.js code:这是我的 Index.js 代码:


exports.handler = function(event, context) {
    var php = spawn('./php-cgi', ['-v']);

    var output = '';
    php.stdout.on('data', function(data) {
        output += data.toString('utf-8');
    });

    php.on('close', function() {
        context.succeed(output);
    });
};

How I can execute php-cgi.我如何执行 php-cgi。 Thank you谢谢

You need to launch an EC2 instance with AMI Amazon Linux 1 and follow next commands:您需要使用 AMI Amazon Linux 1 启动 EC2 实例并执行以下命令:

mkdir php-lambda
cd php-lambda

Download https://github.com/akrabat/lambda-php/blob/2019-01-02-article/doc/compile_php.sh and execute with the desired version of php sh compile_php.sh 7.3.6下载https://github.com/akrabat/lambda-php/blob/2019-01-02-article/doc/compile_php.sh并使用所需版本的 php sh compile_php.sh 7.3.6 执行

It creates a folder called php-7-bin.它会创建一个名为 php-7-bin 的文件夹。 Inside the folder /bin/php there is the php binary that we need.在文件夹 /bin/php 中有我们需要的 php 二进制文件。

Download bootstrap and runtime.php from: https://github.com/akrabat/lambda-php/tree/2019-01-02-article/layer/php从以下位置下载 bootstrap 和 runtime.php: https : //github.com/akrabat/lambda-php/tree/2019-01-02-article/layer/php

Create a new folder and add php binary, bootstrap and runtime.php to it.创建一个新文件夹并向其中添加 php 二进制文件、bootstrap 和 runtime.php。

Create a zip with this content.使用此内容创建一个 zip。

zip -r9 php-layer.zip *

Create a layer with this zip.用这个 zip 创建一个层。

For using php in a lambda.用于在 lambda 中使用 php。 You need to create a lambda function and select Custom runtime and add the php layer created above.您需要创建一个 lambda 函数并选择自定义运行时并添加上面创建的 php 层。

Create a file for example handler.php and add next code inside it:创建一个文件,例如 handler.php 并在其中添加下一个代码:

<?php
function hello($eventData) : array
{
    echo "Prueba";
    return ["msg" => "hola"];
}

Now your PHP Lambda is working.现在您的 PHP Lambda 正在运行。

I have added some changes to runtime.php so I just receive now json data.我对 runtime.php 添加了一些更改,所以我现在只收到 json 数据。

<?php
/**
 *
 * Modified from: https://github.com/pagnihotry/PHP-Lambda-Runtime/blob/master/runtime/runtime.php
 * Copyright (c) 2018 Parikshit Agnihotry
 *
 * RKA Changes:
 *     - JSON encode result of handler function
 *     - Catch any Throwables and write to error log
 */

/**
 * PHP class to interact with AWS Runtime API
 */
class LambdaRuntime
{
    const POST = "POST";
    const GET = "GET";

    private $url;
    private $functionCodePath;
    private $requestId;
    private $response;
    private $rawEventData;
    private $eventPayload;
    private $handler;

    /**
     * Constructor to initialize the class
     */
    function __construct()
    {
        $this->url = "http://".getenv("AWS_LAMBDA_RUNTIME_API");
        $this->functionCodePath = getenv("LAMBDA_TASK_ROOT");
        $this->handler = getenv("_HANDLER");
    }

    /**
     * Get the current request Id being serviced by the runtime
     */
    public function getRequestId() {
        return $this->requestId;
    }

    /**
     * Get the handler setting defined in AWS Lambda configuration
     */
    public function getHandler() {
        return $this->handler;
    }

    /**
     * Get the current event payload
     */
    public function getEventPayload() {
        return json_decode($this->eventPayload);
    }

    /**
     * Get the buffered response
     */
    public function getResponse() {
        return $this->response;
    }

    /**
     * Reset the response buffer
     */
    public function resetResponse() {
        $this->response = "";
    }

    /**
     * Add string to the response buffer. This is printed out on success.
     */
    public function addToResponse($str) {
        $this->response = $this->response.$str;
    }

    public function flushResponse() {
        $result = $this->curl(
            "/2018-06-01/runtime/invocation/".$this->getRequestId()."/response",
            LambdaRuntime::POST,
            $this->getResponse()
        );
        $this->resetResponse();
    }

    /**
     * Get the Next event data
     */
    public function getNextEventData() {
        $this->rawEventData = $this->curl("/2018-06-01/runtime/invocation/next", LambdaRuntime::GET);

        if(!isset($this->rawEventData["headers"]["lambda-runtime-aws-request-id"][0])) {
            //Handle error
            $this->reportError(
                "MissingEventData",
                "Event data is absent. EventData:".var_export($this->rawEventData, true)
            );
            //setting up response so the while loop does not try to invoke the handler with unexpected data
            return array("error"=>true);
        }

        $this->requestId = $this->rawEventData["headers"]["lambda-runtime-aws-request-id"][0];

        $this->eventPayload = $this->rawEventData["body"];

        return $this->rawEventData;
    }

    /**
     * Report error to Lambda runtime
     */
    public function reportError($errorType, $errorMessage) {
        $errorArray = array("errorType"=>$errorType, "errorMessage"=>$errorMessage);
        $errorPayload = json_encode($errorArray);
        $result = $this->curl(
            "/2018-06-01/runtime/invocation/".$this->getRequestId()."/error",
            LambdaRuntime::POST,
            $errorPayload
        );
    }

    /**
     * Report initialization error with runtime
     */
    public function reportInitError($errorType, $errorMessage) {
        $errorArray = array("errorType"=>$errorType, "errorMessage"=>$errorMessage);
        $errorPayload = json_encode($errorArray);
        $result = $this->curl(
            "/2018-06-01/runtime/init/error",
            LambdaRuntime::POST,
            $errorPayload
        );
    }

    /**
     * Internal function to make curl requests to the runtime API
     */
    private function curl($urlPath, $method, $payload="") {

        $fullURL = $this->url . $urlPath;

        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $fullURL);
        curl_setopt($ch, CURLOPT_NOBODY, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

        $headers = [];

        // Parse curl headers
        curl_setopt($ch, CURLOPT_HEADERFUNCTION,
          function($curl, $header) use (&$headers)
          {
            $len = strlen($header);
            $header = explode(':', $header, 2);
            if (count($header) < 2) // ignore invalid headers
              return $len;

            $name = strtolower(trim($header[0]));
            if (!array_key_exists($name, $headers))
              $headers[$name] = [trim($header[1])];
            else
              $headers[$name][] = trim($header[1]);

            return $len;
          }
        );

        //handle post request
        if($method == LambdaRuntime::POST) {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
            // Set HTTP Header for POST request
            curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                    'Content-Length: ' . strlen($payload)
                )
            );
        }

        $response = curl_exec($ch);

        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        return array("headers"=>$headers, "body"=>$response, "httpCode" => $httpCode);
    }
}

$lambdaRuntime = new LambdaRuntime();
$handler =  $lambdaRuntime->getHandler();

//Extract file name and function
list($handlerFile , $handlerFunction) = explode(".", $handler);

//Include the handler file
require_once($handlerFile.".php");

//Poll for the next event to be processed

while (true) {

    //Get next event
    $data = $lambdaRuntime->getNextEventData();

    //Check if there was an error that runtime detected with the next event data
    if(isset($data["error"]) && $data["error"]) {
        continue;
    }

    //Process the events
    $eventPayload = $lambdaRuntime->getEventPayload();

    try {
        //Handler is of format Filename.function
        //Execute handler
        $functionReturn = $handlerFunction($eventPayload);
        $json = json_encode($functionReturn, true);
        $lambdaRuntime->addToResponse($json);
    } catch (\Throwable $e) {
        error_log((string)$e);
    }

    //Report result
    $lambdaRuntime->flushResponse();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM