Skip to content

Commit 65fd62d

Browse files
authored
Merge pull request #35 from horike37/add-dynamodb
Add dynamodb proxy
2 parents 4dc4bfd + 3c31406 commit 65fd62d

File tree

17 files changed

+3405
-6326
lines changed

17 files changed

+3405
-6326
lines changed

README.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,29 @@
55

66
This Serverless Framework plugin supports the AWS service proxy integration feature of API Gateway. You can directly connect API Gateway to AWS services without Lambda.
77

8+
## TOC
9+
10+
- [Install](#install)
11+
- [Supported AWS services](#supported-aws-services)
12+
- [How to use](#how-to-use)
13+
- [Kinesis](#kinesis)
14+
- [SQS](#sqs)
15+
- [Customizing request parameters](#customizing-request-parameters)
16+
- [S3](#s3)
17+
- [Customizing request parameters](#customizing-request-parameters-1)
18+
- [Customize the Path Override in API Gateway](#customize-the-path-override-in-api-gateway)
19+
- [Can use greedy, for deeper Folders](#can-use-greedy--for-deeper-folders)
20+
- [SNS](#sns)
21+
- [DynamoDB](#dynamodb)
22+
- [Common API Gateway features](#common-api-gateway-features)
23+
- [Enabling CORS](#enabling-cors)
24+
- [Adding Authorization](#adding-authorization)
25+
- [Using a Custom IAM Role](#using-a-custom-iam-role)
26+
- [Customizing API Gateway parameters](#customizing-api-gateway-parameters)
27+
- [Customizing request body mapping templates](#customizing-request-body-mapping-templates)
28+
- [Kinesis](#kinesis-1)
29+
- [SNS](#sns-1)
30+
831
## Install
932

1033
Run `serverless plugin install` in your Serverless project.
@@ -22,6 +45,7 @@ Please pull request if you are intersted in it.
2245
- SQS
2346
- S3
2447
- SNS
48+
- DynamoDB
2549

2650
## How to use
2751

@@ -226,10 +250,12 @@ custom:
226250
'integration.request.path.object': 'context.requestId'
227251
'integration.request.header.cache-control': "'public, max-age=31536000, immutable'"
228252
```
253+
229254
This will result in API Gateway setting the Path Override attribute to `{bucket}/{folder}/{file}.xml`
230255
So for example if you navigate to the API Gatway endpoint `/language/en` it will fetch the file in S3 from `{bucket}/language/en.xml`
231256

232257
##### Can use greedy, for deeper Folders
258+
233259
The forementioned example can also be shortened by a greedy approach. Thanks to @taylorreece for mentioning this.
234260

235261
```yaml
@@ -278,6 +304,77 @@ Sample request after deploying.
278304
curl https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/sns -d '{"message": "testtest"}' -H 'Content-Type:application/json'
279305
```
280306

307+
### DynamoDB
308+
309+
Sample syntax for DynamoDB proxy in `serverless.yml`. Currently, the supported [DynamoDB Operations](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Operations.html) are `PutItem`, `GetItem` and `DeleteItem`.
310+
311+
```yaml
312+
custom:
313+
apiGatewayServiceProxies:
314+
- dynamodb:
315+
path: /dynamodb/{id}/{sort}
316+
method: put
317+
tableName: { Ref: 'YourTable' }
318+
hashKey: # set pathParam or queryStringParam as a partitionkey.
319+
pathParam: id
320+
attributeType: S
321+
rangeKey: # required if also using sort key. set pathParam or queryStringParam.
322+
pathParam: sort
323+
attributeType: S
324+
action: PutItem # specify action to the table what you want
325+
condition: attribute_not_exists(Id) # optional Condition Expressions parameter for the table
326+
cors: true
327+
- dynamodb:
328+
path: /dynamodb
329+
method: get
330+
tableName: { Ref: 'YourTable' }
331+
hashKey:
332+
queryStringParam: id # use query string parameter
333+
attributeType: S
334+
rangeKey:
335+
queryStringParam: sort
336+
attributeType: S
337+
action: GetItem
338+
cors: true
339+
- dynamodb:
340+
path: /dynamodb/{id}
341+
method: delete
342+
tableName: { Ref: 'YourTable' }
343+
hashKey:
344+
pathParam: id
345+
attributeType: S
346+
action: DeleteItem
347+
cors: true
348+
349+
resources:
350+
Resources:
351+
YourTable:
352+
Type: AWS::DynamoDB::Table
353+
Properties:
354+
TableName: YourTable
355+
AttributeDefinitions:
356+
- AttributeName: id
357+
AttributeType: S
358+
- AttributeName: sort
359+
AttributeType: S
360+
KeySchema:
361+
- AttributeName: id
362+
KeyType: HASH
363+
- AttributeName: sort
364+
KeyType: RANGE
365+
ProvisionedThroughput:
366+
ReadCapacityUnits: 1
367+
WriteCapacityUnits: 1
368+
```
369+
370+
Sample request after deploying.
371+
372+
```bash
373+
curl -XPUT https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/dynamodb/<hashKey>/<sortkey> \
374+
-d '{"name":{"S":"john"},"address":{"S":"xxxxx"}}' \
375+
-H 'Content-Type:application/json'
376+
```
377+
281378
## Common API Gateway features
282379

283380
### Enabling CORS
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
service: multiple-dynamodb-proxy
2+
3+
provider:
4+
name: aws
5+
runtime: nodejs10.x
6+
7+
plugins:
8+
localPath: './../../../../../../'
9+
modules:
10+
- serverless-apigateway-service-proxy
11+
12+
custom:
13+
apiGatewayServiceProxies:
14+
- dynamodb:
15+
path: /dynamodb/{id}/{sort}
16+
method: put
17+
tableName:
18+
Ref: MyMuTestTable
19+
hashKey:
20+
pathParam: id
21+
attributeType: S
22+
rangeKey:
23+
pathParam: sort
24+
attributeType: S
25+
action: PutItem
26+
cors: true
27+
- dynamodb:
28+
path: /dynamodb
29+
method: get
30+
tableName:
31+
Ref: MyMuTestTable
32+
action: GetItem
33+
hashKey:
34+
queryStringParam: id
35+
attributeType: S
36+
rangeKey:
37+
queryStringParam: sort
38+
attributeType: S
39+
cors: true
40+
- dynamodb:
41+
path: /dynamodb/{id}
42+
method: delete
43+
tableName:
44+
Ref: MyMuTestTable
45+
action: DeleteItem
46+
hashKey:
47+
pathParam: id
48+
attributeType: S
49+
rangeKey:
50+
queryStringParam: sort
51+
attributeType: S
52+
cors: true
53+
54+
resources:
55+
Resources:
56+
MyMuTestTable:
57+
Type: AWS::DynamoDB::Table
58+
Properties:
59+
TableName: MyMuTestTable
60+
AttributeDefinitions:
61+
- AttributeName: id
62+
AttributeType: S
63+
- AttributeName: sort
64+
AttributeType: S
65+
KeySchema:
66+
- AttributeName: id
67+
KeyType: HASH
68+
- AttributeName: sort
69+
KeyType: RANGE
70+
ProvisionedThroughput:
71+
ReadCapacityUnits: 1
72+
WriteCapacityUnits: 1
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
'use strict'
2+
3+
const expect = require('chai').expect
4+
const fetch = require('node-fetch')
5+
const _ = require('lodash')
6+
const {
7+
deployWithRandomStage,
8+
removeService,
9+
getDynamodbItemWithHashKeyAndRangeKey,
10+
putDynamodbItem,
11+
cleanUpDynamodbItems
12+
} = require('../../../utils')
13+
14+
describe('Multiple Dynamodb Proxies Integration Test', () => {
15+
let endpoint
16+
let stage
17+
const tableName = 'MyMuTestTable'
18+
const hashKeyAttribute = 'id'
19+
const rangeKeyAttribute = 'sort'
20+
const hashKey = { S: 'myid' }
21+
const sortKey = { S: 'mykey' }
22+
const config = '__tests__/integration/dynamodb/multiple-integrations/service/serverless.yml'
23+
24+
beforeAll(async () => {
25+
const result = await deployWithRandomStage(config)
26+
27+
stage = result.stage
28+
endpoint = result.endpoint
29+
})
30+
31+
afterAll(async () => {
32+
removeService(stage, config)
33+
})
34+
35+
afterEach(async () => {
36+
await cleanUpDynamodbItems(tableName, hashKeyAttribute, rangeKeyAttribute)
37+
})
38+
39+
it('should get correct response from dynamodb PutItem action endpoint', async () => {
40+
const putEndpoint = `${endpoint}/dynamodb/${hashKey.S}/${sortKey.S}`
41+
42+
const putResponse = await fetch(putEndpoint, {
43+
method: 'PUT',
44+
headers: { 'Content-Type': 'application/json' },
45+
body: JSON.stringify({ message: { S: 'test' } })
46+
})
47+
expect(putResponse.headers.get('access-control-allow-origin')).to.deep.equal('*')
48+
expect(putResponse.status).to.be.equal(200)
49+
50+
const item = await getDynamodbItemWithHashKeyAndRangeKey(
51+
tableName,
52+
hashKeyAttribute,
53+
hashKey,
54+
rangeKeyAttribute,
55+
sortKey
56+
)
57+
expect(item).to.be.deep.equal({
58+
Item: {
59+
[hashKeyAttribute]: hashKey,
60+
[rangeKeyAttribute]: sortKey,
61+
message: { S: 'test' }
62+
}
63+
})
64+
})
65+
66+
it('should get correct response from dynamodb GetItem action endpoint', async () => {
67+
await putDynamodbItem(
68+
tableName,
69+
_.merge(
70+
{},
71+
{ [hashKeyAttribute]: hashKey, [rangeKeyAttribute]: sortKey },
72+
{ message: { S: 'testtest' } }
73+
)
74+
)
75+
const getEndpoint = `${endpoint}/dynamodb?id=${hashKey.S}&sort=${sortKey.S}`
76+
77+
const getResponse = await fetch(getEndpoint, {
78+
method: 'GET',
79+
headers: { 'Content-Type': 'application/json' }
80+
})
81+
expect(getResponse.headers.get('access-control-allow-origin')).to.deep.equal('*')
82+
expect(getResponse.status).to.be.equal(200)
83+
84+
const item = await getResponse.json()
85+
expect(item).to.be.deep.equal({
86+
id: hashKey.S,
87+
sort: sortKey.S,
88+
message: 'testtest'
89+
})
90+
})
91+
92+
it('should get correct response from dynamodb DeleteItem action endpoint', async () => {
93+
await putDynamodbItem(
94+
tableName,
95+
_.merge(
96+
{},
97+
{ [hashKeyAttribute]: hashKey, [rangeKeyAttribute]: sortKey },
98+
{ message: { S: 'test' } }
99+
)
100+
)
101+
const deleteEndpoint = `${endpoint}/dynamodb/${hashKey.S}?sort=${sortKey.S}`
102+
103+
const deleteResponse = await fetch(deleteEndpoint, {
104+
method: 'DELETE',
105+
headers: { 'Content-Type': 'application/json' }
106+
})
107+
expect(deleteResponse.headers.get('access-control-allow-origin')).to.deep.equal('*')
108+
expect(deleteResponse.status).to.be.equal(200)
109+
110+
const item = await getDynamodbItemWithHashKeyAndRangeKey(
111+
tableName,
112+
hashKeyAttribute,
113+
hashKey,
114+
rangeKeyAttribute,
115+
sortKey
116+
)
117+
expect(item).to.be.empty
118+
})
119+
})
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
service: dynamodb-proxy
2+
3+
provider:
4+
name: aws
5+
runtime: nodejs10.x
6+
7+
plugins:
8+
localPath: './../../../../../../'
9+
modules:
10+
- serverless-apigateway-service-proxy
11+
12+
custom:
13+
apiGatewayServiceProxies:
14+
- dynamodb:
15+
path: /dynamodb/{id}
16+
method: post
17+
tableName:
18+
Ref: MyTestTable
19+
action: PutItem
20+
hashKey:
21+
pathParam: 'id'
22+
attributeType: 'S'
23+
cors: true
24+
25+
resources:
26+
Resources:
27+
MyTestTable:
28+
Type: AWS::DynamoDB::Table
29+
Properties:
30+
TableName: MyTestTable
31+
AttributeDefinitions:
32+
- AttributeName: id
33+
AttributeType: S
34+
KeySchema:
35+
- AttributeName: id
36+
KeyType: HASH
37+
ProvisionedThroughput:
38+
ReadCapacityUnits: 1
39+
WriteCapacityUnits: 1

0 commit comments

Comments
 (0)