Skip to content

Commit 3424143

Browse files
Merge branch 'master' into feature/support_s3
2 parents 0122a96 + 9c450d0 commit 3424143

File tree

23 files changed

+2236
-167
lines changed

23 files changed

+2236
-167
lines changed

README.md

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,33 @@
22
[![Build Status](https://travis-ci.org/horike37/serverless-apigateway-service-proxy.svg?branch=master)](https://travis-ci.org/horike37/serverless-apigateway-service-proxy) [![npm version](https://badge.fury.io/js/serverless-apigateway-service-proxy.svg)](https://badge.fury.io/js/serverless-apigateway-service-proxy) [![Coverage Status](https://coveralls.io/repos/github/horike37/serverless-apigateway-service-proxy/badge.svg?branch=master)](https://coveralls.io/github/horike37/serverless-apigateway-service-proxy?branch=master) [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)
33

44
# Serverless APIGateway Service Proxy(BETA)
5+
56
This Serverless Framewrok plugin supports the AWS service proxy integration feature of API Gateway. You can directly connect API Gateway to AWS services without Lambda.
67

78
## Install
9+
810
Run `servelress plugin install` in your Serverless project.
911

10-
```
11-
$ serverless plugin install -n serverless-apigateway-service-proxy
12+
```bash
13+
serverless plugin install -n serverless-apigateway-service-proxy
1214
```
1315

1416
## Supported AWS services
17+
1518
Here is a services list which this plugin supports for now. But will expand to other services in the feature.
1619
Please pull request if you are intersted in it.
1720

1821
- Kinesis Streams
1922
- SQS
2023

2124
## How to use
25+
2226
Define settings of the AWS services you want to integrate under `custom > apiGatewayServiceProxies` and run `serverless deploy`.
2327

2428
### Kinesis
29+
2530
Sample syntax for Kinesis proxy in serverless.yml.
31+
2632
```yaml
2733
custom:
2834
apiGatewayServiceProxies:
@@ -41,34 +47,38 @@ resources:
4147
```
4248
4349
Sample request after deploying.
44-
```
50+
51+
```bash
4552
curl -XPOST https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/kinesis -d '{"Data": "some data","PartitionKey": "some key"}' -H 'Content-Type:application/json'
4653
```
4754
4855
### SQS
4956
5057
Sample syntax for SQS proxy in serverless.yml.
58+
5159
```yaml
5260
custom:
5361
apiGatewayServiceProxies:
5462
- sqs:
5563
path: /sqs
5664
method: post
57-
queueName: {"Fn::GetAtt":[ "SQSQueue", "QueueName" ]}
65+
queueName: { 'Fn::GetAtt': ['SQSQueue', 'QueueName'] }
5866
cors: true
5967

6068
resources:
6169
Resources:
6270
SQSQueue:
63-
Type: "AWS::SQS::Queue"
71+
Type: 'AWS::SQS::Queue'
6472
```
6573
6674
Sample request after deploying.
67-
```
75+
76+
```bash
6877
curl -XPOST https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/sqs -d '{"message": "testtest"}' -H 'Content-Type:application/json'
6978
```
7079
7180
## Common API Gateway features
81+
7282
### Enabling CORS
7383
7484
To set CORS configurations for your HTTP endpoints, simply modify your event configurations as follows:
@@ -143,7 +153,40 @@ custom:
143153
cacheControl: 'max-age=600, s-maxage=600, proxy-revalidate' # Caches on browser and proxy for 10 minutes and doesnt allow proxy to serve out of date content
144154
```
145155
146-
### Customizing request body mapping templates
156+
### Adding Authorization
157+
158+
You can pass in any supported authorization type:
159+
160+
```yml
161+
custom:
162+
apiGatewayServiceProxies:
163+
- sqs:
164+
path: /sqs
165+
method: post
166+
queueName: { 'Fn::GetAtt': ['SQSQueue', 'QueueName'] }
167+
cors: true
168+
169+
# optional - defaults to 'NONE'
170+
authorizationType: 'AWS_IAM' # can be one of ['NONE', 'AWS_IAM', 'CUSTOM', 'COGNITO_USER_POOLS']
171+
172+
# when using 'CUSTOM' authorization type, one should specify authorizerId
173+
# authorizerId: { Ref: 'AuthorizerLogicalId' }
174+
# when using 'COGNITO_USER_POOLS' authorization type, one can specify a list of authorization scopes
175+
# authorizationScopes: ['scope1','scope2']
176+
177+
resources:
178+
Resources:
179+
SQSQueue:
180+
Type: 'AWS::SQS::Queue'
181+
```
182+
183+
Source: [AWS::ApiGateway::Method docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-method.html#cfn-apigateway-method-authorizationtype)
184+
185+
## Specific features
186+
187+
### Kinesis
188+
189+
#### Customizing request body mapping templates
147190
148191
If you'd like to add content types or customize the default templates, you can do so by including your custom [API Gateway request mapping template](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html) in `serverless.yml` like so:
149192

@@ -169,4 +212,29 @@ custom:
169212
- MyStreamArn:
170213
Fn::GetAtt: [MyStream, Arn]
171214
```
215+
172216
Source: [How to connect SNS to Kinesis for cross-account delivery via API Gateway](https://theburningmonk.com/2019/07/how-to-connect-sns-to-kinesis-for-cross-account-delivery-via-api-gateway/)
217+
218+
### SQS
219+
220+
#### Customizing request parameters
221+
222+
If you'd like to pass additional data to the integration request, you can do so by including your custom [API Gateway request parameters](https://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html) in `serverless.yml` like so:
223+
224+
```yml
225+
custom:
226+
apiGatewayServiceProxies:
227+
- sqs:
228+
path: /queue
229+
method: post
230+
queueName: !GetAtt MyQueue.QueueName
231+
cors: true
232+
233+
requestParameters:
234+
'integration.request.querystring.MessageAttribute.1.Name': "'cognitoIdentityId'"
235+
'integration.request.querystring.MessageAttribute.1.Value.StringValue': 'context.identity.cognitoIdentityId'
236+
'integration.request.querystring.MessageAttribute.1.Value.DataType': "'String'"
237+
'integration.request.querystring.MessageAttribute.2.Name': "'cognitoAuthenticationProvider'"
238+
'integration.request.querystring.MessageAttribute.2.Value.StringValue': 'context.identity.cognitoAuthenticationProvider'
239+
'integration.request.querystring.MessageAttribute.2.Value.DataType': "'String'"
240+
```
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
service: multiple-kinesis-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+
- kinesis:
15+
path: /kinesis1
16+
method: post
17+
streamName: { Ref: 'YourStream1' }
18+
cors: true
19+
20+
- kinesis:
21+
path: /kinesis2
22+
method: post
23+
streamName: { Ref: 'YourStream2' }
24+
cors: true
25+
26+
- kinesis:
27+
path: /kinesis3
28+
method: post
29+
streamName: { Ref: 'YourStream3' }
30+
cors: true
31+
32+
resources:
33+
Resources:
34+
YourStream1:
35+
Type: AWS::Kinesis::Stream
36+
Properties:
37+
ShardCount: 1
38+
YourStream2:
39+
Type: AWS::Kinesis::Stream
40+
Properties:
41+
ShardCount: 1
42+
YourStream3:
43+
Type: AWS::Kinesis::Stream
44+
Properties:
45+
ShardCount: 1
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use strict'
2+
3+
const expect = require('chai').expect
4+
const fetch = require('node-fetch')
5+
const { deployWithRandomStage, removeService } = require('../../../utils')
6+
7+
describe('Multiple Kinesis Proxy Integrations Test', () => {
8+
let endpoint
9+
let stage
10+
const config = '__tests__/integration/kinesis/multiple-integrations/service/serverless.yml'
11+
12+
beforeAll(async () => {
13+
const result = await deployWithRandomStage(config)
14+
stage = result.stage
15+
endpoint = result.endpoint
16+
})
17+
18+
afterAll(() => {
19+
removeService(stage, config)
20+
})
21+
22+
it('should get correct response from multiple kinesis proxy endpoints', async () => {
23+
const streams = ['kinesis1', 'kinesis2', 'kinesis3']
24+
25+
for (const stream of streams) {
26+
const testEndpoint = `${endpoint}/${stream}`
27+
28+
const response = await fetch(testEndpoint, {
29+
method: 'POST',
30+
headers: { 'Content-Type': 'application/json' },
31+
body: JSON.stringify({ Data: `data for stream ${stream}`, PartitionKey: 'some key' })
32+
})
33+
expect(response.headers.get('access-control-allow-origin')).to.deep.equal('*')
34+
expect(response.status).to.be.equal(200)
35+
const body = await response.json()
36+
expect(body).to.have.own.property('ShardId')
37+
expect(body).to.have.own.property('SequenceNumber')
38+
}
39+
})
40+
})

__tests__/integration/kinesis/service/serverless.yml renamed to __tests__/integration/kinesis/single-integration/service/serverless.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ provider:
55
runtime: nodejs10.x
66

77
plugins:
8-
localPath: './../'
8+
localPath: './../../../../../../'
99
modules:
1010
- serverless-apigateway-service-proxy
1111

__tests__/integration/kinesis/tests.js renamed to __tests__/integration/kinesis/single-integration/tests.js

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,17 @@
22

33
const expect = require('chai').expect
44
const fetch = require('node-fetch')
5-
const { deployService, removeService, getApiGatewayEndpoint } = require('./../../utils')
5+
const { deployWithRandomStage, removeService } = require('../../../utils')
66

7-
describe('Kinesis Proxy Integration Test', () => {
7+
describe('Single Kinesis Proxy Integration Test', () => {
88
let endpoint
9-
let stackName
109
let stage
11-
const config = '__tests__/integration/kinesis/service/serverless.yml'
10+
const config = '__tests__/integration/kinesis/single-integration/service/serverless.yml'
1211

1312
beforeAll(async () => {
14-
stage = Math.random()
15-
.toString(32)
16-
.substring(2)
17-
stackName = 'kinesis-proxy-' + stage
18-
deployService(stage, config)
19-
endpoint = await getApiGatewayEndpoint(stackName)
13+
const result = await deployWithRandomStage(config)
14+
stage = result.stage
15+
endpoint = result.endpoint
2016
})
2117

2218
afterAll(() => {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
service: multiple-sqs-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+
- sqs:
15+
path: /sqs1
16+
method: post
17+
queueName: { 'Fn::GetAtt': ['SQSQueue1', 'QueueName'] }
18+
cors: true
19+
20+
- sqs:
21+
path: /sqs2
22+
method: post
23+
queueName: { 'Fn::GetAtt': ['SQSQueue2', 'QueueName'] }
24+
cors: true
25+
26+
- sqs:
27+
path: /sqs3
28+
method: post
29+
queueName: { 'Fn::GetAtt': ['SQSQueue3', 'QueueName'] }
30+
cors: true
31+
32+
resources:
33+
Resources:
34+
SQSQueue1:
35+
Type: 'AWS::SQS::Queue'
36+
SQSQueue2:
37+
Type: 'AWS::SQS::Queue'
38+
SQSQueue3:
39+
Type: 'AWS::SQS::Queue'
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
'use strict'
2+
3+
const expect = require('chai').expect
4+
const fetch = require('node-fetch')
5+
const { deployWithRandomStage, removeService } = require('../../../utils')
6+
7+
describe('Multiple SQS Proxy Integrations Test', () => {
8+
let endpoint
9+
let stage
10+
const config = '__tests__/integration/sqs/multiple-integrations/service/serverless.yml'
11+
12+
beforeAll(async () => {
13+
const result = await deployWithRandomStage(config)
14+
stage = result.stage
15+
endpoint = result.endpoint
16+
})
17+
18+
afterAll(() => {
19+
removeService(stage, config)
20+
})
21+
22+
it('should get correct response from multiple sqs proxy endpoints', async () => {
23+
const queues = ['sqs1', 'sqs2', 'sqs3']
24+
25+
for (const queue of queues) {
26+
const testEndpoint = `${endpoint}/${queue}`
27+
const response = await fetch(testEndpoint, {
28+
method: 'POST',
29+
headers: { 'Content-Type': 'application/json' },
30+
body: JSON.stringify({ message: `message for ${queue}` })
31+
})
32+
expect(response.headers.get('access-control-allow-origin')).to.deep.equal('*')
33+
expect(response.status).to.be.equal(200)
34+
const body = await response.json()
35+
expect(body.SendMessageResponse.SendMessageResult).to.have.own.property(
36+
'MD5OfMessageAttributes'
37+
)
38+
expect(body.SendMessageResponse.SendMessageResult).to.have.own.property('MD5OfMessageBody')
39+
expect(body.SendMessageResponse.SendMessageResult).to.have.own.property('MessageId')
40+
expect(body.SendMessageResponse.SendMessageResult).to.have.own.property('SequenceNumber')
41+
expect(body.SendMessageResponse.ResponseMetadata).to.have.own.property('RequestId')
42+
}
43+
})
44+
})

__tests__/integration/sqs/service/serverless.yml renamed to __tests__/integration/sqs/single-integration/service/serverless.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ provider:
55
runtime: nodejs10.x
66

77
plugins:
8-
localPath: './../'
8+
localPath: './../../../../../../'
99
modules:
1010
- serverless-apigateway-service-proxy
1111

@@ -14,10 +14,10 @@ custom:
1414
- sqs:
1515
path: /sqs
1616
method: post
17-
queueName: {"Fn::GetAtt":[ "SQSQueue", "QueueName" ]}
17+
queueName: { 'Fn::GetAtt': ['SQSQueue', 'QueueName'] }
1818
cors: true
1919

2020
resources:
2121
Resources:
2222
SQSQueue:
23-
Type: "AWS::SQS::Queue"
23+
Type: 'AWS::SQS::Queue'

0 commit comments

Comments
 (0)