Do you want to request a feature or report a bug?
Bug
What is the current behavior?
Invoking a lambda function returns a 404.
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem.
This is the output I get:
$ amplify function invoke TestingBackend GET /items
Using service: Lambda, provided by: awscloudformation
? Provide the name of the script file that contains your handler function: index.js
? Provide the name of the handler function to invoke: handler
Running "lambda_invoke:default" (lambda_invoke) task
EVENT: {"key1":"value1","key2":"value2","key3":"value3"}
App started
EADDRINUSE /tmp/server0.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server1.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server2.sock incrementing socketPathSuffix.
Success! Message:
------------------
{"statusCode":404,"body":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot GET /</pre>\n</body>\n</html>\n","headers":{"x-powered-by":"Express","access-control-allow-origin":"*","access-control-allow-headers":"Origin, X-Requested-With, Content-Type, Accept","content-security-policy":"default-src 'self'","x-content-type-options":"nosniff","content-type":"text/html; charset=utf-8","content-length":"139","date":"Sun, 26 Aug 2018 10:55:57 GMT","connection":"close"},"isBase64Encoded":false}
Done.
Done running invoke function.
What is the expected behavior?
The response should not be a 404 but a 200 with api gateway event.
Which versions of Amplify CLI, and which OS are affected by this issue? Did this work in previous versions?
0.1.14
This is basically a follow on of #10.
@jarrettj The lambda function got invoked and it tried to spin up a local express server on port 3000 but it couldn’t succeed since there was an app already running on your machine on port 3000. You could either kill the process on port 3000 or change the App.js code in the src/ dir to make the express server run on a different port.
I have nothing running on 3000? Maybe it is Mac OS related? Or I am missing a package?
I've tried deleting the /tmp/server* files and rerun it again. Same error.
Then I did as you said and changed the port to 3001, and still same error.
Also, every invoke of the function gives another line that says the EADDRINUSE even though it is not.
Running "lambda_invoke:default" (lambda_invoke) task
EVENT: {"key1":"value1","key2":"value2","key3":"value3"}
App started
EADDRINUSE /tmp/server0.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server1.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server2.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server3.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server4.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server5.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server6.sock incrementing socketPathSuffix.
@jarrettj .This seems to be an issue with a previous version of aws-serverless-express lib ->
https://github.com/awslabs/aws-serverless-express/issues/5
I was able to reproduce this. Here are the steps you could make this work.
1) In your amplify/function/"aws-serverless-express": "^2.2.0"
to "aws-serverless-express": "^3.3.5"
.
2) Run amplify function build
3) Run amplify function invoke <function-name>
Btw, I saw that you're issuing the amplify function invoke TestingBackend GET /items
command. We don't accept the GET /items
as params, instead what you could do is that you can mock the amplify/function/
{
"httpMethod": "GET",
"body": "{\"name\": \"Amplify\"}",
"path": "/items",
"resource": "/{proxy+}",
"queryStringParameters": {}
}
Thanks dude. Will give that a try! Making awsmobile-cli assumptions, my bad. :)
On 26 Aug 2018, at 16:40, Kaustav Ghosh notifications@github.com wrote:
@jarrettj https://github.com/jarrettj .This seems to be an issue with a previos version of aws-serverless-express lib ->
awslabs/aws-serverless-express#5 https://github.com/awslabs/aws-serverless-express/issues/5
I was able to reproduce this. Here are the steps you could make this work.In your amplify/function//src/package.json update "aws-serverless-express": "^2.2.0" to "aws-serverless-express": "^3.3.5".
Run amplify function build
Run `amplify function invoke
Btw, I saw that you're issuing the amplify function invoke TestingBackend GET /items command. We don't accept the GET /items as params, instead what you could do is that you can mock the amplify/function//src/event.json file with the following{
"httpMethod": "GET",
"body": "{\"name\": \"Amplify\"}",
"path": "/items",
"resource": "/{proxy+}",
"queryStringParameters": {}
}
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/aws-amplify/amplify-cli/issues/25#issuecomment-416043633, or mute the thread https://github.com/notifications/unsubscribe-auth/AAvdS88auA__4klgp7cWT9i81G2j0ok9ks5uUrNPgaJpZM4WMvMw.
No luck man. Did all that. And it's in no way changes I have made. It is just the generated function. And it won't run.
Does the status code still show a 404 even after replacing the event.json with the JSON mentioned above? Are you still getting the EADDRINUSE error after updating the package.json with the latest aws-serverless version?
$ amplify function invoke Categories
Using service: Lambda, provided by: awscloudformation
? Provide the name of the script file that contains your handler function: index.js
? Provide the name of the handler function to invoke: handler
Running "lambda_invoke:default" (lambda_invoke) task
EVENT: {"key1":"value1","key2":"value2","key3":"value3"}
App started
Success! Message:
------------------
{"statusCode":404,"body":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot GET /</pre>\n</body>\n</html>\n","headers":{"x-powered-by":"Express","access-control-allow-origin":"*","access-control-allow-headers":"Origin, X-Requested-With, Content-Type, Accept","content-security-policy":"default-src 'self'","x-content-type-options":"nosniff","content-type":"text/html; charset=utf-8","content-length":"139","date":"Sun, 26 Aug 2018 15:24:32 GMT","connection":"close"},"isBase64Encoded":false}
Done.
Done running invoke function.
@jarrettj As you can see, the event.json is not modified and is still
EVENT: {"key1":"value1","key2":"value2","key3":"value3"}
You need to replace your amplify/function/<function-name>
/src/event.json with this (as mentioned above)
{
"httpMethod": "GET",
"body": "{\"name\": \"Amplify\"}",
"path": "/items",
"resource": "/{proxy+}",
"queryStringParameters": {}
}
^^^ this would invoke the GET /items route:
You should see something like this:
f45c89966b0d:67my kaustavg$ amplify function invoke myfunc
Using service: Lambda, provided by: awscloudformation
? Provide the name of the script file that contains your handler function: index.js
? Provide the name of the handler function to invoke: handler
Running "lambda_invoke:default" (lambda_invoke) task
EVENT: {"httpMethod":"GET","body":"{\"name\": \"Amplify\"}","path":"/items","resource":"/{proxy+}","queryStringParameters":{}}
App started
Im here!Success!
Success! Message:
------------------
{"statusCode":200,"body":"{\"httpMethod\":\"GET\",\"path\":\"/items\",\"resource\":\"/{proxy+}\",\"queryStringParameters\":{}}","headers":{"x-powered-by":"Express","access-control-allow-origin":"*","access-control-allow-headers":"Origin, X-Requested-With, Content-Type, Accept","content-type":"application/json; charset=utf-8","content-length":"86","etag":"W/\"56-Z3MOFJii3Fmzatdyu53q6vKmubU\"","date":"Sun, 26 Aug 2018 15:34:15 GMT","connection":"close"},"isBase64Encoded":false}
Done.
Done running invoke function.
I don't see why the event would be the issue? Updated the event.json.
$ amplify function invoke Categories
Using service: Lambda, provided by: awscloudformation
? Provide the name of the script file that contains your handler function: index.js
? Provide the name of the handler function to invoke: handler
Running "lambda_invoke:default" (lambda_invoke) task
EVENT: {"httpMethod":"GET","body":"{\"name\": \"Amplify\"}","path":"/items","resource":"/{proxy+}","queryStringParameters":{}}
App started
Success! Message:
------------------
{"statusCode":404,"body":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot GET /items</pre>\n</body>\n</html>\n","headers":{"x-powered-by":"Express","access-control-allow-origin":"*","access-control-allow-headers":"Origin, X-Requested-With, Content-Type, Accept","content-security-policy":"default-src 'self'","x-content-type-options":"nosniff","content-type":"text/html; charset=utf-8","content-length":"144","date":"Sun, 26 Aug 2018 15:39:26 GMT","connection":"close"},"isBase64Encoded":false}
Done.
Done running invoke function.
In you app.js do you a route which looks like this?
app.get('/items', function(req, res) {
// Add your code here
// Return the API Gateway event and query string parameters for example
res.json(req.apiGateway.event);
});
It is the generated file. No changes.
/*
Copyright 2017 - 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at
http://aws.amazon.com/apache2.0/
or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.
*/
var express = require('express')
var bodyParser = require('body-parser')
var awsServerlessExpressMiddleware = require('aws-serverless-express/middleware')
// declare a new express app
var app = express()
app.use(bodyParser.json())
app.use(awsServerlessExpressMiddleware.eventContext())
// Enable CORS for all methods
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*")
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
next()
});
/**********************
* Example get method *
**********************/
app.get('/categories', function(req, res) {
// Add your code here
// Return the API Gateway event and query string parameters for example
res.json(req.apiGateway.event);
});
app.get('/categories/*', function(req, res) {
// Add your code here
res.json({success: 'get call succeed!', url: req.url});
});
/****************************
* Example post method *
****************************/
app.post('/categories', function(req, res) {
// Add your code here
res.json({success: 'post call succeed!', url: req.url, body: req.body})
});
app.post('/categories/*', function(req, res) {
// Add your code here
res.json({success: 'post call succeed!', url: req.url, body: req.body})
});
/****************************
* Example post method *
****************************/
app.put('/categories', function(req, res) {
// Add your code here
res.json({success: 'put call succeed!', url: req.url, body: req.body})
});
app.put('/categories/*', function(req, res) {
// Add your code here
res.json({success: 'put call succeed!', url: req.url, body: req.body})
});
/****************************
* Example delete method *
****************************/
app.delete('/categories', function(req, res) {
// Add your code here
res.json({success: 'delete call succeed!', url: req.url});
});
app.delete('/categories/*', function(req, res) {
// Add your code here
res.json({success: 'delete call succeed!', url: req.url});
});
app.listen(3000, function() {
console.log("App started")
});
// Export the app object. When executing the application local this does nothing. However,
// to port it to AWS Lambda we will create a wrapper around that will load the app from
// this file
module.exports = app
In your event.json replace /items
with /categories
since you have a GET /categories route instead of GET /items route.
Success!!! Legend! Thanks.
So now that I can run it locally to test, can my app access it locally? Or do I have to do a push for that? Still having publish issues.
@jarrettj That's an excellent question. Are you using Amplify JS lib in your frontend code to interact with the API's?
I'm needing to use a URL endpoint. Instead of the amplifyjs lib way. Thanks for the help so far.
So the amplify invoke <function-name>
command actually starts a server running on your localhost at port 3000 (do not kill the process after you run this command). So from your app if you can call GET http://localhost:3000/categories and that should give you the results back based on your logic in your app.js file in the app.get('/categories) function.
From your app.js file in the app.get('/categories) function you might want to replace res.json(req.apiGateway.event);
with res.json({success: 'get call succeeded!', url: req.url});
or anything else based on what you would like to return back to your app from the API call.
Hi,
Good day.
Thanks, updated. I get the following response:
Missing x-apigateway-event or x-apigateway-context header(s)
I am using Postman, just did a get on http://localhost:3000/api/categories.
Regards.
@jarrettj We don't yet have a good story around locally testing resources before pushing it to the cloud and we have plans in the future to make this possible.
To make this work for now for local app testing you could remove app.use(awsServerlessExpressMiddleware.eventContext())
from your app.js code in src/ and see if that works. Please remember to uncomment or add this back to your code before deployment since this would be critical for API Gateway -> Lambda invokation once deployed.
Cool, I'll just have to push to live prod then for now. :(
The change you noted does not work. If I remove that line, the function is not reachable any longer. The request does not make it to the server.
Regards.
All working fine now. Really appreciate all the help. :-D 👍
any way to do this with amplify mock ???
doing something similar I get
EVENT: {"httpMethod":"GET","body":"{\"name\": \"Amplify\"}","path":"/influencer/registration","resource":"/{proxy+}","queryStringParameters":{}}
Result:
null
Finished execution.
No server started, and the process finish right away
Most helpful comment
@jarrettj We don't yet have a good story around locally testing resources before pushing it to the cloud and we have plans in the future to make this possible.
To make this work for now for local app testing you could remove
app.use(awsServerlessExpressMiddleware.eventContext())
from your app.js code in src/ and see if that works. Please remember to uncomment or add this back to your code before deployment since this would be critical for API Gateway -> Lambda invokation once deployed.