Skip to content

Commit

Permalink
feat: add custom mapping example
Browse files Browse the repository at this point in the history
* Request mapping functions must now return the body
* Renamed CONTEXT_SUCCEED to CONTEXT
* socketPath no longer needs to be returned by request mapping function
  • Loading branch information
brettstack committed Jun 19, 2019
1 parent a9c01a3 commit fe99c85
Show file tree
Hide file tree
Showing 22 changed files with 2,631 additions and 52 deletions.
65 changes: 58 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@ npm install aws-serverless-express

```js
// lambda.js
const awsServerlessExpress = require('aws-serverless-express')
const { configure } = require('aws-serverless-express')
const app = require('./app')
const servererlessExpress = awsServerlessExpress.configure({
})

exports.handler = (event, context) => { awsServerlessExpress.proxy(server, event, context) }
const servererlessExpress = configure({ app })
exports.handler = servererlessExpress.handler
```

[Package and create your Lambda function](http://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html), then configure a simple proxy API using Amazon API Gateway and integrate it with your Lambda function.
[Package and create your Lambda function](http://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html), then configure a simple proxy API using Amazon API Gateway and integrate it with your Lambda function. See the [basic starter example](examples/basic-starter) to get started.

## Quick Start/Example

Expand All @@ -32,7 +30,60 @@ Want to get up and running quickly? [Check out our basic starter example](exampl
- [Serverless Application Model (SAM)](https://github.com/awslabs/serverless-application-model)/[CloudFormation](https://aws.amazon.com/cloudformation/aws-cloudformation-templates/) template
- Helper scripts to configure, deploy, and manage your application

## Accessing the event and context objects
## API

## resolutionMode

Lambda supports three methods to end the execution and return a result: context, callback, and promise. By default, aws-serverless-express uses promise resolution, but you can specify 'CONTEXT' or 'CALLBACK' ('PROMISE' by default) if you need to change this. If you specify 'CALLBACK', then `context.callbackWaitsForEmptyEventLoop = false` is also set for you.

```js
configure({
app,
resolutionMode: 'CALLBACK'
})
```

## eventFns

aws-serverless-express natively supports API Gateway, ALB, and Lambda@Edge. If you want to use Express with other AWS Services which can invoke a Lambda Function you can provide your own custom request/response mappings via `eventFns`. See the [custom-mapper-dynamodb example](examples/custom-mapper-dynamodb).

```js
function requestMapper ({ event }) {
// Your logic here...

return {
method,
path,
headers
}
}

function responseMapper ({
statusCode,
body,
headers,
isBase64Encoded
}) {
// Your logic here...

return {
statusCode,
body,
headers,
isBase64Encoded
}
}

configure({
app,
eventFns: {
request: requestMapper,
response: responseMapper
}
})
```

### Accessing the event and context objects

This package exposes a function to easily get the `event` and `context` objects Lambda receives from the event source.

Expand Down
19 changes: 9 additions & 10 deletions __tests__/unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,36 +75,35 @@ function mapApiGatewayEventToHttpRequest (multiValueHeaders = {}) {
const context = {
'foo': 'bar'
}
const socketPath = '/tmp/server0.sock'
const httpRequest = awsServerlessExpressEventMappings.mapApiGatewayEventToHttpRequest({ event, context, socketPath })
const httpRequest = awsServerlessExpressEventMappings.mapApiGatewayEventToHttpRequest({ event, context })

return {httpRequest, eventClone, context}
}

test('mapApiGatewayEventToHttpRequest: with headers', () => {
const r = mapApiGatewayEventToHttpRequest({'x-foo': ['foo']})

expect(r.httpRequest.body).toBeInstanceOf(Buffer)
delete r.httpRequest.body
expect(r.httpRequest).toEqual({
method: 'GET',
path: '/foo',
headers: {
'x-foo': 'foo',
'Content-Length': Buffer.byteLength('Hello serverless!')
},
socketPath: '/tmp/server0.sock'
}
})
})

test('mapApiGatewayEventToHttpRequest: without headers', () => {
const r = mapApiGatewayEventToHttpRequest()

expect(r.httpRequest.body).toBeInstanceOf(Buffer)
delete r.httpRequest.body
expect(r.httpRequest).toEqual({
method: 'GET',
path: '/foo',
headers: {
'Content-Length': Buffer.byteLength('Hello serverless!')
},
socketPath: '/tmp/server0.sock'
}
})
})

Expand Down Expand Up @@ -376,13 +375,13 @@ describe('forwardResponse: content-type encoding', () => {
})

describe('makeResolver', () => {
test('CONTEXT_SUCCEED (specified)', () => {
test('CONTEXT (specified)', () => {
return new Promise(
(resolve) => {
const context = new MockContext(resolve)
const contextResolver = awsServerlessExpressTransport.makeResolver({
context,
resolutionMode: 'CONTEXT_SUCCEED'
resolutionMode: 'CONTEXT'
})

return contextResolver.succeed({
Expand Down
10 changes: 6 additions & 4 deletions examples/alb/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## Development

1. `npm pack ../..`
2. `npm install ./aws-serverless-express-3.3.5.tgz`
3. `npm install --prefix ./src ./`
4. `node local.js`
```bash
npm pack ../..
npm install ./aws-serverless-express-3.3.5.tgz
npm install --prefix ./src ./
node local.js
```
5 changes: 1 addition & 4 deletions examples/alb/src/lambda.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
// const awsServerlessExpress = require(process.env.NODE_ENV === 'test' ? '../../index' : 'aws-serverless-express')
const awsServerlessExpress = require('aws-serverless-express')
const app = require('./app')

const ase = awsServerlessExpress.configure({
app,
resolutionMode: 'PROMISE'
// eventSource: ''
app
})

exports.handler = ase.handler
2 changes: 1 addition & 1 deletion examples/basic-starter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"config": {
"s3BucketName": "sls-xpress2",
"region": "us-east-1",
"cloudFormationStackName": "AwsServerlessExpressStackNew",
"cloudFormationStackName": "ServerlessExpress",
"functionName": "AwsServerlessExpressStackNew-ExpressLambdaFunction-GU4XXGPADJ0E"
},
"scripts": {
Expand Down
2 changes: 2 additions & 0 deletions examples/custom-mapper-dynamodb/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
template.packaged.yaml
*.tgz
8 changes: 8 additions & 0 deletions examples/custom-mapper-dynamodb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## Development

```
npm pack ../..
npm install ./aws-serverless-express-3.3.5.tgz
npm install --prefix ./src ./
node local.js
```
28 changes: 28 additions & 0 deletions examples/custom-mapper-dynamodb/dynamodb-event.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"Records": [
{
"eventID": "93eea905b34daefbe0fe8a21858065a8",
"eventName": "INSERT",
"eventVersion": "1.1",
"eventSource": "aws:dynamodb",
"awsRegion": "us-east-1",
"dynamodb": {
"ApproximateCreationDateTime": 1560902007,
"Keys": {
"id": {
"S": "b"
}
},
"NewImage": {
"id": {
"S": "b"
}
},
"SequenceNumber": "200000000000235577791",
"SizeBytes": 6,
"StreamViewType": "NEW_IMAGE"
},
"eventSourceARN": "arn:aws:dynamodb:us-east-1:123123123:table/aws-serverless-express-dynamodb-example-Table-191RH2M1OU01V/stream/2019-06-18T23:42:52.038"
}
]
}
28 changes: 28 additions & 0 deletions examples/custom-mapper-dynamodb/local.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const lambdaFunction = require('./src/lambda.js')
const albEvent = require('./dynamodb-event.json')

const server = lambdaFunction.handler(albEvent, {})
.then(v => {
console.info(v)
process.exit(0)
})
.catch(v => {
console.error(v)
process.exit(1)
})

process.stdin.resume()

function exitHandler (options, err) {
if (options.cleanup && server && server.close) {
server.close()
}

if (err) console.error(err.stack)
if (options.exit) process.exit()
}

process.on('exit', exitHandler.bind(null, { cleanup: true }))
process.on('SIGINT', exitHandler.bind(null, { exit: true })) // ctrl+c event
process.on('SIGTSTP', exitHandler.bind(null, { exit: true })) // ctrl+v event
process.on('uncaughtException', exitHandler.bind(null, { exit: true }))
Loading

0 comments on commit fe99c85

Please sign in to comment.