Reputation: 11
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:
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
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
});
});
}
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.
https://***.execute-api.us-east-1.amazonaws.com/prod/HelloLambda/espnheadlinesimage/{league}/{channel}
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
}
Upvotes: 0
Views: 2621
Reputation: 11
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}
Upvotes: 1
Reputation: 7354
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.
Upvotes: 1