Skip to content

Commit

Permalink
Merge 044d0e2 into d4bc4e1
Browse files Browse the repository at this point in the history
  • Loading branch information
erezrokah committed Aug 20, 2019
2 parents d4bc4e1 + 044d0e2 commit aa6e502
Show file tree
Hide file tree
Showing 23 changed files with 1,744 additions and 13 deletions.
67 changes: 64 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Please pull request if you are intersted in it.
- Kinesis Streams
- SQS
- S3
- SNS

## How to use

Expand Down Expand Up @@ -77,7 +78,7 @@ resources:
Sample request after deploying.

```bash
curl -X POST https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/kinesis -d '{"message": "some data"}' -H 'Content-Type:application/json'
curl https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/kinesis -d '{"message": "some data"}' -H 'Content-Type:application/json'
```

### SQS
Expand All @@ -102,7 +103,7 @@ resources:
Sample request after deploying.

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

#### Customizing request parameters
Expand Down Expand Up @@ -172,7 +173,32 @@ resources:
Sample request after deploying.

```bash
curl -X POST https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/s3 -d '{"message": "testtest"}' -H 'Content-Type:application/json'
curl https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/s3 -d '{"message": "testtest"}' -H 'Content-Type:application/json'
```

### SNS

Sample syntax for SNS proxy in `serverless.yml`.

```yaml
custom:
apiGatewayServiceProxies:
- sns:
path: /sns
method: post
topicName: { 'Fn::GetAtt': ['SNSTopic', 'TopicName'] }
cors: true

resources:
Resources:
SNSTopic:
Type: AWS::SNS::Topic
```

Sample request after deploying.

```bash
curl https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/sns -d '{"message": "testtest"}' -H 'Content-Type:application/json'
```

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

### Customizing request body mapping templates

#### Kinesis

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:

```yml
# Required for using Fn::Sub
plugins:
- serverless-cloudformation-sub-variables

custom:
apiGatewayServiceProxies:
- kinesis:
Expand All @@ -307,4 +339,33 @@ custom:
Fn::GetAtt: [MyStream, Arn]
```

> It is important that the mapping template will return a valid `application/json` string
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/)

#### SNS

Similar to the [Kinesis](#kinesis-1) support, you can customize the default request mapping templates in `serverless.yml` like so:

```yml
# Required for using Fn::Sub
plugins:
- serverless-cloudformation-sub-variables

custom:
apiGatewayServiceProxies:
- kinesis:
path: /sns
method: post
topicName: { 'Fn::GetAtt': ['SNSTopic', 'TopicName'] }
request:
template:
application/json:
Fn::Sub:
- "Action=Publish&Message=$util.urlEncode('This is a fixed message')&TopicArn=$util.urlEncode('#{MyTopicArn}')"
- MyTopicArn: { Ref: MyTopic }
```

> It is important that the mapping template will return a valid `application/x-www-form-urlencoded` string
Source: [Connect AWS API Gateway directly to SNS using a service integration](https://www.alexdebrie.com/posts/aws-api-gateway-service-proxy/)
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
service: sns-proxy

provider:
name: aws
runtime: nodejs10.x
stage: ${opt:stage, 'dev'}

plugins:
localPath: './../../../../../../'
modules:
- serverless-apigateway-service-proxy

custom:
apiGatewayServiceProxies:
- sns:
path: /sns
method: post
topicName: { 'Fn::GetAtt': ['SNSTopic', 'TopicName'] }
cors: true
request:
template:
application/json:
'Fn::Join':
- ''
- - "Action=Publish&Message=$util.urlEncode('This is a fixed message')&TopicArn=$util.urlEncode('"
- { Ref: SNSTopic }
- "')"

resources:
Resources:
SNSTopic:
Type: AWS::SNS::Topic
Properties:
Subscription:
- Endpoint: { 'Fn::GetAtt': ['SqsQueue', 'Arn'] }
Protocol: sqs

SqsQueue:
Type: AWS::SQS::Queue

SqsQueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
PolicyDocument:
Version: '2012-10-17'
Id: SqsQueuePolicy
Statement:
- Sid: Allow-SendMessage-To-Queue-From-SNS-Topic
Effect: Allow
Principal: "*"
Action:
- sqs:SendMessage
Resource: "*"
Condition:
ArnEquals:
aws:SourceArn:
Ref: SNSTopic

Queues:
- Ref: SqsQueue

Outputs:
SqsQueueUrl:
Value: { Ref: SqsQueue }
61 changes: 61 additions & 0 deletions __tests__/integration/sns/custom-mapping-template/tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use strict'

const { default: awsTesting } = require('aws-testing-library/lib/chai')
const chai = require('chai')
chai.use(awsTesting)
const { expect } = chai

const fetch = require('node-fetch')
const { deployWithRandomStage, removeService } = require('../../../utils')

describe('Single SNS Proxy Integration Test', () => {
let endpoint
let stage
let region
let queueUrl
const config = '__tests__/integration/sns/custom-mapping-template/service/serverless.yml'

beforeAll(async () => {
;({
stage,
region,
endpoint,
outputs: { SqsQueueUrl: queueUrl }
} = await deployWithRandomStage(config))
})

afterAll(() => {
removeService(stage, config)
})

it('should get correct response from sqs proxy endpoint', async () => {
const testEndpoint = `${endpoint}/sns`

const response = await fetch(testEndpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
})

expect(response.headers.get('access-control-allow-origin')).to.deep.equal('*')
expect(response.status).to.be.equal(200)
const json = await response.json()

expect(json).to.have.own.property('PublishResponse')

expect(json.PublishResponse).to.have.own.property('PublishResult')
expect(json.PublishResponse).to.have.own.property('ResponseMetadata')

expect(json.PublishResponse.PublishResult).to.have.own.property('MessageId')
expect(json.PublishResponse.PublishResult).to.have.own.property('SequenceNumber')

expect(json.PublishResponse.ResponseMetadata).to.have.own.property('RequestId')

const expectedFixedMessage = 'This is a fixed message'
await expect({
region,
queueUrl,
timeout: 10000,
pollEvery: 2500
}).to.have.message((message) => message.Message === expectedFixedMessage)
})
})
103 changes: 103 additions & 0 deletions __tests__/integration/sns/multiple-integrations/service/serverless.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
service: multiple-sns-proxy

provider:
name: aws
runtime: nodejs10.x

plugins:
localPath: './../../../../../../'
modules:
- serverless-apigateway-service-proxy

custom:
apiGatewayServiceProxies:
- sns:
path: /sns1
method: post
topicName: { 'Fn::GetAtt': ['SNSTopic1', 'TopicName'] }
cors: true

- sns:
path: /sns2
method: post
topicName: { 'Fn::GetAtt': ['SNSTopic2', 'TopicName'] }
cors: true

- sns:
path: /sns3
method: post
topicName: { 'Fn::GetAtt': ['SNSTopic3', 'TopicName'] }
cors: true

resources:
Resources:
SNSTopic1:
Type: AWS::SNS::Topic
Properties:
Subscription:
- Endpoint: { 'Fn::GetAtt': ['SqsQueue', 'Arn'] }
Protocol: sqs

SNSTopic2:
Type: AWS::SNS::Topic
Properties:
Subscription:
- Endpoint: { 'Fn::GetAtt': ['SqsQueue', 'Arn'] }
Protocol: sqs

SNSTopic3:
Type: AWS::SNS::Topic
Properties:
Subscription:
- Endpoint: { 'Fn::GetAtt': ['SqsQueue', 'Arn'] }
Protocol: sqs

SqsQueue:
Type: AWS::SQS::Queue

SqsQueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
PolicyDocument:
Version: '2012-10-17'
Id: SqsQueuePolicy
Statement:
- Sid: Allow-SendMessage-To-Queue-From-SNS-Topic1
Effect: Allow
Principal: "*"
Action:
- sqs:SendMessage
Resource: "*"
Condition:
ArnEquals:
aws:SourceArn:
Ref: SNSTopic1

- Sid: Allow-SendMessage-To-Queue-From-SNS-Topic2
Effect: Allow
Principal: "*"
Action:
- sqs:SendMessage
Resource: "*"
Condition:
ArnEquals:
aws:SourceArn:
Ref: SNSTopic2

- Sid: Allow-SendMessage-To-Queue-From-SNS-Topic3
Effect: Allow
Principal: "*"
Action:
- sqs:SendMessage
Resource: "*"
Condition:
ArnEquals:
aws:SourceArn:
Ref: SNSTopic3

Queues:
- Ref: SqsQueue

Outputs:
SqsQueueUrl:
Value: { Ref: SqsQueue }

0 comments on commit aa6e502

Please sign in to comment.