0

I am trying to host a laravel application on aws lambda and call it's routes using aws api gateway. The application is basically a web crawler which fetches web pages from rss feeds.

When I make a call to a laravel route using the url generated by api gateway, laravel redirects the request to '/home' path. However, when I test it on ec2 instance using "node debug" , it works like a charm. Below are the details of the steps I followed.

I followed a fantastic blog written by Chris White for hosting a laravel application on aws lambda.

Steps:

  1. Generating a PHP CGI Binary

    I used "amzn-ami-hvm-2016.03.3.x86_64-gp2" ec2 instance to build my php-cgi binary file

./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 function to spawn PHP CGI process - php.js file

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. Prepare AWS Lambda bundle

    The directory structure of my HelloLambda.zip bundle is

├── api

├── node_modules

├── php-cgi

└── php.js

The api folder consists of my laravel application.

  1. API Gateway - I created a api gateway for my HelloLambda function. The api has league & channel as path parameters. The GET method uses lambda proxy integration. The api shows following url in stages view

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

api-gateway-screenshot.jpg

  1. Make a GET request to api providing the league and channel parameter.

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

When I make this get request, the browser shows a message

Redirecting to http://***.execute-api.us-east-1.amazonaws.com/home

My laravel routes.php file consists of below route

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

Any help would be highly appreciated. Thanks in advance.


Here's the console output of content of my event object in my test API call

{
    "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 Answers 2

1

I don't really know anything about laravel but you have configured a route for espnheadlinesimage/.... but you are actually calling the route HelloLambda/espnheadlinesimage/{league}/{channel} via API GW. The value of requestUri (and event.path) in the Lambda function will be HelloLambda/espnheadlinesimage/nhl/28 in your test API call.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for a prompt reply. You are right, my requestUri is infact /HelloLambda/espnheadlinesimage/nhl/28 in my test API call. I have edited the question with contents of my request API call event object.
Yeah so I'm saying, should that match the 'route' in laravel in this line? Route::get('espnheadlinesimage/{league}/{channel}', 'EspnController@headlinesimage');
Yes, it should match this route in laravel and the 'EspnController' should perform the function 'headlinesimage' with parameters 'nhl' and '28' but I can't figure out why laravel is redirecting to '/home' instead.
I was thinking laravel is redirecting to /home because it doesn't recognize the route you are giving it which is HelloLambda/espnheadlinesimage/nhl/28 rather than the one that you've configured espnheadlinesimage/nhl/28
I tried this and now it works. A silly mistake ! Thanks Jack !
1

This issue is resolved as suggested by Jack.

The issue was that the API url being generated by API Gateway was

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

However the route in my Laravel routes file was

/espnheadlinesimage/{league}/{channel}

My misconception was that the base url of for the lambda function is

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

and I should add route after this path to my laravel routes file, i.e.,

/espnheadlinesimage/{league}/{channel}

However, the path in my route file should include '/HelloLambda' ,i.e., it should be

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.