使用AWS API Gateway调用AWS Lambda上托管的Laravel路由

时间:2017-05-30 10:12:27

标签: php laravel aws-lambda aws-api-gateway

我正在尝试在aws lambda上托管一个laravel应用程序,并使用aws api网关调用它的路由。该应用程序基本上是一个Web爬虫,它从rss提要中获取网页。

当我使用api网关生成的网址拨打laravel路线时,laravel会将请求重定向到' / home'路径。但是,当我使用"节点调试"在ec2实例上测试它时,它就像一个魅力。以下是我所遵循的步骤的详细信息。

我跟随了一篇由Chris White撰写的精彩博客,用于在aws lambda上托管laravel应用程序。

步骤:

  1. 生成PHP CGI二进制文件

    我用过" amzn-ami-hvm-2016.03.3.x86_64-gp2" ec2实例构建我的php-cgi二进制文件

  2.   

    ./ configure --prefix = / tmp / php-7.0.11 / compiled / --without-pear   --enable-shared = no --enable-static = yes --enable-phar --enable-json --disable-all --with-openssl --with-curl --enable-libxml --enable-simplexml - -enable-xml --with-mhash --with-gd --enable-exif --with-freetype-dir --enable-mbstring --enable-sockets --enable-pdo --with-pdo-mysql - enable-tokenizer --enable-session --enable-filter

    1. NodeJS Lambda函数产生PHP CGI进程 - php.js 文件
    2. 
      
      process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT'];
      
      var parser = require('http-string-parser');
      var spawn = require('child_process').spawn;
      exports.handler = function(event, context) {
      
        var requestMethod = event.httpMethod || 'GET';
        var serverName = event.headers ? event.headers.Host : '';
        var requestUri = event.path || '';
        var headers = {};
      
        if (event.headers) {
          Object.keys(event.headers).map(function(key) {
            headers['HTTP_' + key.toUpperCase()] = event.headers[key];
          });
        }
      
        var request_env = Object.assign({
          REDIRECT_STATUS: 1,
          REQUEST_METHOD: requestMethod,
          SCRIPT_FILENAME: 'api/public/index.php',
          SCRIPT_NAME: '/index.php',
          PATH_INFO: '/',
          SERVER_NAME: serverName,
          SERVER_PROTOCOL: 'HTTP/1.1',
          REQUEST_URI: requestUri
        }, headers);
      
        var php = spawn('./php-cgi', ['api/public/index.php'], {
          env: request_env
        });
      
        var response = '';
      
        php.stdout.on('data', function(data) {
          response += data.toString('utf-8');
        });
      
        php.stderr.on('data', function(data) {
          console.log("STDERR: " + data.toString());
        });
      
        php.on('close', function(code) {
      
          var parsedResponse = parser.parseResponse(response);
          context.succeed({
            isBase64Encoded: false,
            statusCode: parsedResponse.statusCode || 200,
            headers: parsedResponse.headers,
            body: parsedResponse.body
          });
      
        });
      
      }
      
      
      

      1. 准备AWS Lambda软件包

        HelloLambda.zip 捆绑包的目录结构是

      2. ├──api

        ├──node_modules

        ├──php-cgi

        └──php.js

        api文件夹由我的laravel应用程序组成。

        1. API网关 - 我为HelloLambda函数创建了一个api网关。 api有联盟&通道作为路径参数。 GET方法使用lambda代理集成。 api在阶段视图中显示以下url
        2.   

          的https://***.execute-api.us-east-1.amazonaws.com/prod/HelloLambda/espnheadlinesimage/ {联赛} / {信道}

          api-gateway-screenshot.jpg

          1. 向api发出GET请求,提供联盟和频道参数。
          2.   

            的https://***.execute-api.us-east-1.amazonaws.com/prod/HelloLambda/espnheadlinesimage/nhl/28

            当我发出此请求时,浏览器会显示一条消息

              

            重定向到http://***.execute-api.us-east-1.amazonaws.com/home

            我的laravel routes.php文件包含以下路径

            Route::get('espnheadlinesimage/{league}/{channel}', 'EspnController@headlinesimage');
            

            任何帮助都将受到高度赞赏。提前谢谢。

            这是我的测试API调用中我的事件对象内容的控制台输出

            {
                "resource": "/HelloLambda/espnheadlinesimage/{league}/{channel}",
                "path": "/HelloLambda/espnheadlinesimage/nhl/48",
                "httpMethod": "GET",
                "headers": {
                    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
                    "Accept-Encoding": "gzip, deflate, sdch, br",
                    "Accept-Language": "en-GB,en;q=0.8,en-US;q=0.6,hi;q=0.4",
                    "CloudFront-Forwarded-Proto": "https",
                    "CloudFront-Is-Desktop-Viewer": "true",
                    "CloudFront-Is-Mobile-Viewer": "false",
                    "CloudFront-Is-SmartTV-Viewer": "false",
                    "CloudFront-Is-Tablet-Viewer": "false",
                    "CloudFront-Viewer-Country": "IN",
                    "Host": "x7pdbfnzsg.execute-api.us-east-1.amazonaws.com",
                    "upgrade-insecure-requests": "1",
                    "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
                    "Via": "2.0 0e9493f2bcf9035541b227fce2ae5798.cloudfront.net (CloudFront)",
                    "X-Amz-Cf-Id": "93vabUcIQzqON2X5ive3a0nHmqcO47wFzNEBR0SMs39Wo1qlNK9bIA==",
                    "X-Amzn-Trace-Id": "Root=1-592e3ff4-132417a71f64bb62205997f7",
                    "X-Forwarded-For": "103.243.10.67, 54.182.231.71",
                    "X-Forwarded-Port": "443",
                    "X-Forwarded-Proto": "https"
                },
                "queryStringParameters": null,
                "pathParameters": {
                    "channel": "48",
                    "league": "nhl"
                },
                "stageVariables": null,
                "requestContext": {
                    "path": "/prod/HelloLambda/espnheadlinesimage/nhl/48",
                    "accountId": "729779362209",
                    "resourceId": "kbrsfu",
                    "stage": "prod",
                    "requestId": "bd922c44-45b5-11e7-81ca-777f94f39a98",
                    "identity": {
                        "cognitoIdentityPoolId": null,
                        "accountId": null,
                        "cognitoIdentityId": null,
                        "caller": null,
                        "apiKey": "",
                        "sourceIp": "103.243.10.67",
                        "accessKey": null,
                        "cognitoAuthenticationType": null,
                        "cognitoAuthenticationProvider": null,
                        "userArn": null,
                        "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
                        "user": null
                    },
                    "resourcePath": "/HelloLambda/espnheadlinesimage/{league}/{channel}",
                    "httpMethod": "GET",
                    "apiId": "x7pdbfnzsg"
                },
                "body": null,
                "isBase64Encoded": false
            } 
            

2 个答案:

答案 0 :(得分:1)

我对laravel一无所知,但您已为espnheadlinesimage/....配置了路线,但实际上是通过API GW呼叫路由HelloLambda/espnheadlinesimage/{league}/{channel}。 Lambda函数中requestUri(和event.path)的值将在您的测试API调用中为HelloLambda/espnheadlinesimage/nhl/28

答案 1 :(得分:1)

此问题已按照Jack的建议解决。

问题是API网关生成的API网址是

  

/ HelloLambda / espnheadlinesimage / {联赛} / {信道}

然而,我的Laravel路线文件中的路线是

  

/ espnheadlinesimage / {联赛} / {信道}

我的误解是lambda函数的基本URL是

  

的https://***.execute-api.us-east-1.amazonaws.com/prod/HelloLambda/

我应该在这条路径之后添加路线到我的laravel路线文件,即

  

/ espnheadlinesimage / {联赛} / {信道}

但是,我的路径文件中的路径应该包含' / HelloLambda' ,即它应该是

  

/ HelloLambda / espnheadlinesimage / {联赛} / {信道}