Skip to content

Commit cef0219

Browse files
authored
Merge pull request #25 from erezrokah/feature/support-sns
Feature: add sns support
2 parents d4bc4e1 + 044d0e2 commit cef0219

File tree

23 files changed

+1744
-13
lines changed

23 files changed

+1744
-13
lines changed

README.md

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Please pull request if you are intersted in it.
2121
- Kinesis Streams
2222
- SQS
2323
- S3
24+
- SNS
2425

2526
## How to use
2627

@@ -77,7 +78,7 @@ resources:
7778
Sample request after deploying.
7879
7980
```bash
80-
curl -X POST https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/kinesis -d '{"message": "some data"}' -H 'Content-Type:application/json'
81+
curl https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/kinesis -d '{"message": "some data"}' -H 'Content-Type:application/json'
8182
```
8283
8384
### SQS
@@ -102,7 +103,7 @@ resources:
102103
Sample request after deploying.
103104

104105
```bash
105-
curl -X POST https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/sqs -d '{"message": "testtest"}' -H 'Content-Type:application/json'
106+
curl https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/sqs -d '{"message": "testtest"}' -H 'Content-Type:application/json'
106107
```
107108

108109
#### Customizing request parameters
@@ -172,7 +173,32 @@ resources:
172173
Sample request after deploying.
173174

174175
```bash
175-
curl -X POST https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/s3 -d '{"message": "testtest"}' -H 'Content-Type:application/json'
176+
curl https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/s3 -d '{"message": "testtest"}' -H 'Content-Type:application/json'
177+
```
178+
179+
### SNS
180+
181+
Sample syntax for SNS proxy in `serverless.yml`.
182+
183+
```yaml
184+
custom:
185+
apiGatewayServiceProxies:
186+
- sns:
187+
path: /sns
188+
method: post
189+
topicName: { 'Fn::GetAtt': ['SNSTopic', 'TopicName'] }
190+
cors: true
191+
192+
resources:
193+
Resources:
194+
SNSTopic:
195+
Type: AWS::SNS::Topic
196+
```
197+
198+
Sample request after deploying.
199+
200+
```bash
201+
curl https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/sns -d '{"message": "testtest"}' -H 'Content-Type:application/json'
176202
```
177203

178204
## Common API Gateway features
@@ -282,9 +308,15 @@ Source: [AWS::ApiGateway::Method docs](https://docs.aws.amazon.com/AWSCloudForma
282308

283309
### Customizing request body mapping templates
284310

311+
#### Kinesis
312+
285313
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:
286314

287315
```yml
316+
# Required for using Fn::Sub
317+
plugins:
318+
- serverless-cloudformation-sub-variables
319+
288320
custom:
289321
apiGatewayServiceProxies:
290322
- kinesis:
@@ -307,4 +339,33 @@ custom:
307339
Fn::GetAtt: [MyStream, Arn]
308340
```
309341

342+
> It is important that the mapping template will return a valid `application/json` string
343+
310344
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/)
345+
346+
#### SNS
347+
348+
Similar to the [Kinesis](#kinesis-1) support, you can customize the default request mapping templates in `serverless.yml` like so:
349+
350+
```yml
351+
# Required for using Fn::Sub
352+
plugins:
353+
- serverless-cloudformation-sub-variables
354+
355+
custom:
356+
apiGatewayServiceProxies:
357+
- kinesis:
358+
path: /sns
359+
method: post
360+
topicName: { 'Fn::GetAtt': ['SNSTopic', 'TopicName'] }
361+
request:
362+
template:
363+
application/json:
364+
Fn::Sub:
365+
- "Action=Publish&Message=$util.urlEncode('This is a fixed message')&TopicArn=$util.urlEncode('#{MyTopicArn}')"
366+
- MyTopicArn: { Ref: MyTopic }
367+
```
368+
369+
> It is important that the mapping template will return a valid `application/x-www-form-urlencoded` string
370+
371+
Source: [Connect AWS API Gateway directly to SNS using a service integration](https://www.alexdebrie.com/posts/aws-api-gateway-service-proxy/)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
service: sns-proxy
2+
3+
provider:
4+
name: aws
5+
runtime: nodejs10.x
6+
stage: ${opt:stage, 'dev'}
7+
8+
plugins:
9+
localPath: './../../../../../../'
10+
modules:
11+
- serverless-apigateway-service-proxy
12+
13+
custom:
14+
apiGatewayServiceProxies:
15+
- sns:
16+
path: /sns
17+
method: post
18+
topicName: { 'Fn::GetAtt': ['SNSTopic', 'TopicName'] }
19+
cors: true
20+
request:
21+
template:
22+
application/json:
23+
'Fn::Join':
24+
- ''
25+
- - "Action=Publish&Message=$util.urlEncode('This is a fixed message')&TopicArn=$util.urlEncode('"
26+
- { Ref: SNSTopic }
27+
- "')"
28+
29+
resources:
30+
Resources:
31+
SNSTopic:
32+
Type: AWS::SNS::Topic
33+
Properties:
34+
Subscription:
35+
- Endpoint: { 'Fn::GetAtt': ['SqsQueue', 'Arn'] }
36+
Protocol: sqs
37+
38+
SqsQueue:
39+
Type: AWS::SQS::Queue
40+
41+
SqsQueuePolicy:
42+
Type: AWS::SQS::QueuePolicy
43+
Properties:
44+
PolicyDocument:
45+
Version: '2012-10-17'
46+
Id: SqsQueuePolicy
47+
Statement:
48+
- Sid: Allow-SendMessage-To-Queue-From-SNS-Topic
49+
Effect: Allow
50+
Principal: "*"
51+
Action:
52+
- sqs:SendMessage
53+
Resource: "*"
54+
Condition:
55+
ArnEquals:
56+
aws:SourceArn:
57+
Ref: SNSTopic
58+
59+
Queues:
60+
- Ref: SqsQueue
61+
62+
Outputs:
63+
SqsQueueUrl:
64+
Value: { Ref: SqsQueue }
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
'use strict'
2+
3+
const { default: awsTesting } = require('aws-testing-library/lib/chai')
4+
const chai = require('chai')
5+
chai.use(awsTesting)
6+
const { expect } = chai
7+
8+
const fetch = require('node-fetch')
9+
const { deployWithRandomStage, removeService } = require('../../../utils')
10+
11+
describe('Single SNS Proxy Integration Test', () => {
12+
let endpoint
13+
let stage
14+
let region
15+
let queueUrl
16+
const config = '__tests__/integration/sns/custom-mapping-template/service/serverless.yml'
17+
18+
beforeAll(async () => {
19+
;({
20+
stage,
21+
region,
22+
endpoint,
23+
outputs: { SqsQueueUrl: queueUrl }
24+
} = await deployWithRandomStage(config))
25+
})
26+
27+
afterAll(() => {
28+
removeService(stage, config)
29+
})
30+
31+
it('should get correct response from sqs proxy endpoint', async () => {
32+
const testEndpoint = `${endpoint}/sns`
33+
34+
const response = await fetch(testEndpoint, {
35+
method: 'POST',
36+
headers: { 'Content-Type': 'application/json' }
37+
})
38+
39+
expect(response.headers.get('access-control-allow-origin')).to.deep.equal('*')
40+
expect(response.status).to.be.equal(200)
41+
const json = await response.json()
42+
43+
expect(json).to.have.own.property('PublishResponse')
44+
45+
expect(json.PublishResponse).to.have.own.property('PublishResult')
46+
expect(json.PublishResponse).to.have.own.property('ResponseMetadata')
47+
48+
expect(json.PublishResponse.PublishResult).to.have.own.property('MessageId')
49+
expect(json.PublishResponse.PublishResult).to.have.own.property('SequenceNumber')
50+
51+
expect(json.PublishResponse.ResponseMetadata).to.have.own.property('RequestId')
52+
53+
const expectedFixedMessage = 'This is a fixed message'
54+
await expect({
55+
region,
56+
queueUrl,
57+
timeout: 10000,
58+
pollEvery: 2500
59+
}).to.have.message((message) => message.Message === expectedFixedMessage)
60+
})
61+
})
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
service: multiple-sns-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+
- sns:
15+
path: /sns1
16+
method: post
17+
topicName: { 'Fn::GetAtt': ['SNSTopic1', 'TopicName'] }
18+
cors: true
19+
20+
- sns:
21+
path: /sns2
22+
method: post
23+
topicName: { 'Fn::GetAtt': ['SNSTopic2', 'TopicName'] }
24+
cors: true
25+
26+
- sns:
27+
path: /sns3
28+
method: post
29+
topicName: { 'Fn::GetAtt': ['SNSTopic3', 'TopicName'] }
30+
cors: true
31+
32+
resources:
33+
Resources:
34+
SNSTopic1:
35+
Type: AWS::SNS::Topic
36+
Properties:
37+
Subscription:
38+
- Endpoint: { 'Fn::GetAtt': ['SqsQueue', 'Arn'] }
39+
Protocol: sqs
40+
41+
SNSTopic2:
42+
Type: AWS::SNS::Topic
43+
Properties:
44+
Subscription:
45+
- Endpoint: { 'Fn::GetAtt': ['SqsQueue', 'Arn'] }
46+
Protocol: sqs
47+
48+
SNSTopic3:
49+
Type: AWS::SNS::Topic
50+
Properties:
51+
Subscription:
52+
- Endpoint: { 'Fn::GetAtt': ['SqsQueue', 'Arn'] }
53+
Protocol: sqs
54+
55+
SqsQueue:
56+
Type: AWS::SQS::Queue
57+
58+
SqsQueuePolicy:
59+
Type: AWS::SQS::QueuePolicy
60+
Properties:
61+
PolicyDocument:
62+
Version: '2012-10-17'
63+
Id: SqsQueuePolicy
64+
Statement:
65+
- Sid: Allow-SendMessage-To-Queue-From-SNS-Topic1
66+
Effect: Allow
67+
Principal: "*"
68+
Action:
69+
- sqs:SendMessage
70+
Resource: "*"
71+
Condition:
72+
ArnEquals:
73+
aws:SourceArn:
74+
Ref: SNSTopic1
75+
76+
- Sid: Allow-SendMessage-To-Queue-From-SNS-Topic2
77+
Effect: Allow
78+
Principal: "*"
79+
Action:
80+
- sqs:SendMessage
81+
Resource: "*"
82+
Condition:
83+
ArnEquals:
84+
aws:SourceArn:
85+
Ref: SNSTopic2
86+
87+
- Sid: Allow-SendMessage-To-Queue-From-SNS-Topic3
88+
Effect: Allow
89+
Principal: "*"
90+
Action:
91+
- sqs:SendMessage
92+
Resource: "*"
93+
Condition:
94+
ArnEquals:
95+
aws:SourceArn:
96+
Ref: SNSTopic3
97+
98+
Queues:
99+
- Ref: SqsQueue
100+
101+
Outputs:
102+
SqsQueueUrl:
103+
Value: { Ref: SqsQueue }

0 commit comments

Comments
 (0)