dherault / dherault/serverless-offline
How to run lambda integration mode in serverless locally
- Dominant language
- JavaScript
- Stars
- 5.3k
- Forks
- 811
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 3
Description
I want to run serverless application locally earlier this was working using lambda proxy but I want to change it to lambda integration. So I have defined request and response template as follows but when I invoke lambda locally, I see this response,
{
"isBase64Encoded": false,
"statusCode": 200,
"headers": {
"access-control-allow-origin": "*",
"content-type": "application/json; charset=utf-8",
"content-length": "2",
"etag": "W/\"2-l9Fw4VUO7kr8CvBlt4zaMCqXZ0w\""
},
body
:
"{\"error\":\"[{\\\"error\\\":\\\"Invalid query parameters\\\",\\\"messages\\\":[\\\"'page' is required\\\",\\\"'pagesize' is required\\\"]}]\"}"
}
and I expect only body in response this breaks running UI locally , when I run the application in aws I get correct response. Is there any additional configuration to be done in serverless.yml. This is how serverless.yml looks like
service: my-service-api
provider:
name: aws
runtime: nodejs16.x
memorySize: 256
timeout: 10
region: us-west-2
profile: xyz
versionFunctions: false
endpointType: regional
deploymentBucket:
name: ps-serverless
vpc: xyz
apiGateway:
restApiId: xyz
restApiRootResourceId: xyz
restApiResources:
/district-settings: xyz
plugins:
- serverless-offline
custom:
corsOptions:
origin: http://localhost:3000/
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
- X-Xsrf-Token
allowCredentials: true
requestTemplate:
application/json: |
#set($request_header = $input.params().header)
#set($request_query = $input.params().querystring)
#set($request_path = $input.params().path)
#set($request_stage_vars = $stageVariables)
#set($request_context = $context)
{
"body": "$util.escapeJavaScript($input.json('$'))",
"httpMethod": "$context.httpMethod",
"headers": {
#foreach($header in $request_header.keySet())
"$header" : "$util.escapeJavaScript($request_header.get($header))"
#if($foreach.hasNext),#end
#end
},
"queryStringParameters": {
#foreach($query in $request_query.keySet())
"$query" : "$util.urlDecode($request_query.get($query))"
#if($foreach.hasNext),#end
#end
},
"pathParameters": {
#foreach($path in $request_path.keySet())
"$path" : "$util.escapeJavaScript($request_path.get($path))"
#if($foreach.hasNext),#end
#end
},
"stageVariables": {
#foreach($stage in $request_stage_vars.keySet())
"$stage" : "$util.escapeJavaScript($request_stage_vars.get($stage))"
#if($foreach.hasNext),#end
#end
},
"resource": "$context.resourcePath",
"path":"$context.path",
"requestContext": {
#foreach($reqContext in $request_context.keySet())
"$reqContext" : "$util.escapeJavaScript($request_context.get($reqContext))"
#if($foreach.hasNext),#end
#end
},
"isBase64Encoded": false
}
responseHeaders:
headers:
Content-Type: ${env:CONTENT_TYPE}
Access-Control-Allow-Credentials: ${env:ALLOW_CREDENTIAL}
Strict-Transport-Security: ${env:SECURE_TRANSPORT_SECURITY}
Cache-Control: ${env:CACHE_CONTROL}
Content-Security-Policy: ${env:DEFAULT_CSP}
X-Content-Type-Options: ${env:CONTENT_TYPE_OPTIONS}
X-XSS-Protection: ${env:XSS_PROTECTION}
X-Frame-Options: ${env:X_FRAME_OPTIONS}
Pragma: ${env:PRAGMA}
statusCodes:
200:
pattern: ''
template:
application/json: |
#set($body = $input.json('$.body'))
#set($statusCode = $input.json('$.statusCode'))
#set($Integer = 0)
$util.parseJson($body)
#set($origin = $input.params().header)
#set($context.responseOverride.header.Access-Control-Allow-Origin = $origin)
#if($body.contains("error"))
#set($context.responseOverride.status = $Integer.parseInt($statusCode))
#end
functions:
listDistricts:
handler: src/districts/district-handler.list
events:
- http:
path: 'district'
method: get
cors: ${self:custom.corsOptions}
integration: lambda
request:
passThrough: NEVER
template: ${self:custom.requestTemplate}
response: ${self:custom.responseHeaders}
Any additional configuration I need to configure to get correct only body in response running locally will be of great help. Also I have GET request with query params that is not passed.
Please note I am using serverless-offline@8.8.1, node version 16. I am running app locally using sls offline start.
this is the lambda code
async (req: Request, res: Response, next: NextFunction): Promise => {
try {
const districtListQueryParam: DistrictListQueryParam = (req.query as unknown) as DistrictListQueryParam;
const districtList = <>
res.status(HttpStatusCodes.OK).send(districtList);
} catch (err) {
logger.error(`Error while listing the districts ${err.message}`);
next(err);
}
}
This is the error message in terminal from catch ,
{"filename":"http-error-middleware.js","level":"error","message":"Error: [{\"error\":\"Invalid query parameters\",\"messages\":[\"'page' is required\". ....
Replies:1 comment
karthikpower
2 days ago
Author
[offline] _____ REQUEST TEMPLATE PROCESSING _____
[offline] Velocity rendered: {
"body": "{}",
"httpMethod": "GET",
"headers": {
"Host" : "localhost:3000"
, "Connection" : "keep-alive"
, "sec-ch-ua" : ""Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115""
, "Accept" : "application/json, text/plain, /"
, "sec-ch-ua-mobile" : "?0"
, "User-Agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
, "sec-ch-ua-platform" : ""macOS""
, "Origin" : "http://localhost:8000/"
, "Sec-Fetch-Site" : "same-site"
, "Sec-Fetch-Mode" : "cors"
, "Sec-Fetch-Dest" : "empty"
, "Referer" : "http://localhost:8000/"
, "Accept-Encoding" : "gzip, deflate, br"
, "Accept-Language" : "en-GB,en-US;q=0.9,en;q=0.8"
},
"queryStringParameters": {
"page" : '1'
, "pagesize" : '12'
},
....
[offline] event: {}
This is what I see in terminal : though request template is processed but event is printed as empty. Though I have serverless-offline plugin
Contributor guide
Research direction
Reproduce the GET district request with sls offline start using the shown serverless.yml, request template, response template, and src/districts/district-handler.list entry point. Compare the rendered request with the empty event and verify that query parameters reach the handler and that the local response contains only the expected body, matching AWS behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, javascript, node.js
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100