【问题标题】:Calling Laravel Routes hosted on AWS Lambda using AWS API Gateway使用 AWS API Gateway 调用托管在 AWS Lambda 上的 Laravel 路由
【发布时间】:2017-10-30 18:15:53
【问题描述】:

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

当我使用 api gateway 生成的 url 调用 laravel 路由时,laravel 将请求重定向到“/home”路径。但是,当我使用 "node debug" 在 ec2 实例上测试它时,它就像一个魅力。以下是我遵循的步骤的详细信息。

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

步骤:

  1. 生成 PHP CGI 二进制文件

    我使用“amzn-ami-hvm-2016.03.3.x86_64-gp2”ec2 实例来构建我的 php-cgi 二进制文件

./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 文件

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 包的目录结构是

├── api

├── 节点模块

├── php-cgi

└── php.js

api 文件夹包含我的 laravel 应用程序。

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

https://***.execute-api.us-east-1.amazonaws.com/prod/HelloLambda/espnheadlinesimage/{league}/{channel}

api-gateway-screenshot.jpg

  1. 向提供联赛和频道参数的 api 发出 GET 请求。

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
} 

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • 感谢您的及时回复。你是对的,我的 requestUri 在我的测试 API 调用中实际上是 /HelloLambda/espnheadlinesimage/nhl/28。我已经用我的请求 API 调用事件对象的内容编辑了问题。
    • 是的,我是说,这应该与这一行中 laravel 中的“路线”相匹配吗? Route::get('espnheadlinesimage/{league}/{channel}', 'EspnController@headlinesimage');
    • 是的,它应该在 laravel 中匹配这条路线,并且“EspnController”应该使用参数“nhl”和“28”执行函数“headlinesimage”,但我不知道为什么 laravel 会重定向到'/home' 代替。
    • 我在想 laravel 正在重定向到 /home,因为它无法识别你给它的路由 HelloLambda/espnheadlinesimage/nhl/28 而不是你配置的 espnheadlinesimage/nhl/28
    • 我试过了,现在可以了。一个愚蠢的错误!谢谢杰克!
    【解决方案2】:

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

    问题在于 API Gateway 生成的 API url 是

    /HelloLambda/espnheadlinesimage/{league}/{channel}

    但是我的 Laravel 路由文件中的路由是

    /espnheadlinesimage/{league}/{channel}

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

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

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

    /espnheadlinesimage/{league}/{channel}

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

    /HelloLambda/espnheadlinesimage/{league}/{channel}

    【讨论】:

      猜你喜欢
      • 2017-12-07
      • 2020-05-03
      • 2017-05-29
      • 2016-04-30
      • 2020-10-01
      • 2018-09-23
      • 2017-09-19
      • 1970-01-01
      • 2021-04-18
      相关资源
      最近更新 更多