Reputation: 57541
This question is pretty much the same as Serverless offline not getting route, but since that one was not answered I'm asking again. I'm trying to follow this article, https://medium.com/@awesome1888/how-to-use-serverless-locally-with-webpack-and-docker-5e268f71715, on how to deploy a Lambda function with Serverless.
I have a directory with the following structure:
> tree -I node_modules
.
├── package-lock.json
├── package.json
├── serverless.yml
├── src
│ ├── handler.js
│ └── index.js
└── webpack.config.js
where serverless.yml
reads
service: my-first-lambda
plugins:
- serverless-webpack
- serverless-offline
provider:
name: aws
runtime: nodejs10.x
region: us-east-1
stage: dev
functions:
hello:
handler: src/handler.main
events:
- http:
path: /hello
method: any
custom:
webpack:
includeModules: true
src/index.js
reads
import moment from 'moment';
const handler = async (event, context) => {
const body = await new Promise((resolve) => {
setTimeout(() => {
resolve(`Hello, this is your lambda speaking. Today is ${moment().format('dddd')}`)
}, 2000);
});
return {
statusCode: 200,
body,
};
}
export default handler;
src/handler.js
reads
export { default as main } from './index';
and webpack.config.js
reads
const path = require("path");
const nodeExternals = require("webpack-node-externals");
const slsw = require("serverless-webpack");
module.exports = {
entry: slsw.lib.entries,
target: "node",
mode: slsw.lib.webpack.isLocal ? "development" : "production",
externals: [nodeExternals()],
output: {
libraryTarget: "commonjs",
path: path.join(__dirname, ".webpack"),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
plugins: ["@babel/plugin-proposal-object-rest-spread"]
}
}
]
}
]
}
};
The problem is when I start up the function in offline mode, it seems to have only one very specific route:
>
npx serverless offline start --region us-east-1 --noTimeout --port 3000 --host 0.0.0.0
Serverless: Bundling with Webpack...
Time: 1203ms
Built at: 08/30/2019 2:35:10 PM
Asset Size Chunks Chunk Names
src/handler.js 6.81 KiB src/handler [emitted] src/handler
Entrypoint src/handler = src/handler.js
[./src/handler.js] 42 bytes {src/handler} [built]
[./src/index.js] 1.64 KiB {src/handler} [built]
[moment] external "moment" 42 bytes {src/handler} [built]
Serverless: Watching for changes...
Serverless: Starting Offline: dev/us-east-1.
Serverless: Routes for hello:
Serverless: POST /{apiVersion}/functions/my-first-lambda-dev-hello/invocations
Serverless: Offline [HTTP] listening on http://0.0.0.0:3000
Serverless: Enter "rp" to replay the last request
and if I go to http://localhost:3000/hello, I get this response:
{"statusCode":404,"error":"Serverless-offline: route not found.","currentRoute":"get - /hello","existingRoutes":["post - /{apiVersion}/functions/my-first-lambda-dev-hello/invocations"]}
Any idea why this is not working? (I've perused https://serverless.com/framework/docs/ but couldn't quickly find an answer).
Upvotes: 15
Views: 21313
Reputation: 1379
Just pointing out that methods above the path behave differently than other way around for all other methods except GET (facepalm):
route not found:
- http:
method: ANY
path: /
- http:
method: ANY
path: '{proxy+}'
working:
- http:
path: /
method: ANY
- http:
path: '{proxy+}'
method: ANY
Upvotes: 0
Reputation: 5279
I had this issue and if anyone comes across it, this github comment fixed my issue.
You can run $ sls offline start --noPrependStageInUrl
or add the following to your serverless.yml
file
custom:
serverless-offline:
noPrependStageInUrl: true
According to the comment:
I had this problem with anything 6+, this was due to the fact that it now defaults to appending the staging name to the url path. To revert to the old way, you need to add --noPrependStageInUrl to the cli or in the serverless file custom: serverless-offline noPrependStageInUrl: true to revert to previous setting. I'm testing it his out but @dherault the functionality is not reflecting what is actually happening in AWS.
I was using serverless-offline: "6.7.0"
and my index.handler
was as below:
const serverless = require("serverless-http");
const express = require("express");
const app = express();
app.get("/", function (req, res) {
res.send("Hello World!");
});
module.exports.handler = serverless(app);
And my serverless.yml
plugins:
- serverless-offline
custom:
serverless-offline:
noPrependStageInUrl: true
provider:
name: aws
runtime: nodejs12.x
stage: dev
region: eu-west-2
functions:
app:
handler: src/index.handler
events:
- http: ANY /
- http: "ANY {proxy+}"
Apologies this isn't exactly a great answer but hopefully, someone comes across this and it is a solution to their problem.
Upvotes: 21
Reputation: 3777
Looks like you've got a whitespace issue in your serverless.yml
file.
Try indenting path
and method
under the http
block:
functions:
hello:
handler: src/handler.main
events:
- http:
path: /hello
method: any
Upvotes: 12
Reputation: 84
for setup a quick example using serverless template :
sls create -h
output :
create ........................ Create new Serverless service
--template / -t .................... Template for the service. Available templates: "aws-clojure-gradle", "aws-clojurescript-gradle", "aws-nodejs", "aws-nodejs-typescript", "aws-alexa-typescript", "aws-nodejs-ecma-script", "aws-python", "aws-python3", "aws-groovy-gradle", "aws-java-maven", "aws-java-gradle", "aws-kotlin-jvm-maven", "aws-kotlin-jvm-gradle", "aws-kotlin-nodejs-gradle", "aws-scala-sbt", "aws-csharp", "aws-fsharp", "aws-go", "aws-go-dep", "aws-go-mod", "aws-ruby", "aws-provided", "azure-nodejs", "cloudflare-workers", "cloudflare-workers-enterprise", "cloudflare-workers-rust", "fn-nodejs", "fn-go", "google-nodejs", "google-python", "google-go", "kubeless-python", "kubeless-nodejs", "openwhisk-java-maven", "openwhisk-nodejs", "openwhisk-php", "openwhisk-python", "openwhisk-ruby", "openwhisk-swift", "spotinst-nodejs", "spotinst-python", "spotinst-ruby", "spotinst-java8", "plugin" and "hello-world"
step1: so for generated a new nodejs example with an api :
sls create -t aws-nodejs-ecma-script -n service-name-hello-world
step2: install serverless-offline :
npm install serverless-offline -D
step3: in serverless.yml
plugins:
- serverless-webpack
- serverless-offline
step4 : start local server
serverless offline start -r us-west-1 --stage dev
github Example
git clone https://github.com/ysfmag/aws-serverless-nodejs-example
cd aws-serverless-nodejs-example
yarn
yarn start
serverless.yml
to define an api in your serverless framework you need to respect yaml format , and in the path variable you dont need to start with '/hello' just 'hello' will work .
functions:
hello:
handler: src/handler.main
events:
- http:
path: hello
method: get
Upvotes: 0