Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sns): Support raw message delivery #1827

Merged
merged 1 commit into from
Feb 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion packages/@aws-cdk/aws-sns/lib/subscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ export interface SubscriptionProps {
* The topic to subscribe to.
*/
topic: ITopic;

/**
* true if raw message delivery is enabled for the subscription. Raw messages are free of JSON formatting and can be
* sent to HTTP/S and Amazon SQS endpoints. For more information, see GetSubscriptionAttributes in the Amazon Simple
* Notification Service API Reference.
*
* @default false
*/
rawMessageDelivery?: boolean;
}

/**
Expand All @@ -34,10 +43,15 @@ export class Subscription extends Construct {
constructor(scope: Construct, id: string, props: SubscriptionProps) {
super(scope, id);

if (props.rawMessageDelivery && ['http', 'https', 'sqs'].indexOf(props.protocol) < 0) {
throw new Error('Raw message delivery can only be enabled for HTTP/S and SQS subscriptions.');
}

new CfnSubscription(this, 'Resource', {
endpoint: props.endpoint,
protocol: props.protocol,
topicArn: props.topic.topicArn
topicArn: props.topic.topicArn,
rawMessageDelivery: props.rawMessageDelivery,
});

}
Expand Down
23 changes: 14 additions & 9 deletions packages/@aws-cdk/aws-sns/lib/topic-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,12 @@ export abstract class TopicBase extends cdk.Construct implements ITopic {
/**
* Subscribe some endpoint to this topic
*/
public subscribe(name: string, endpoint: string, protocol: SubscriptionProtocol): Subscription {
public subscribe(name: string, endpoint: string, protocol: SubscriptionProtocol, rawMessageDelivery?: boolean): Subscription {
return new Subscription(this, name, {
topic: this,
endpoint,
protocol
protocol,
rawMessageDelivery,
});
}

Expand All @@ -134,8 +135,9 @@ export abstract class TopicBase extends cdk.Construct implements ITopic {
*
* @param name The subscription name
* @param queue The target queue
* @param rawMessageDelivery Enable raw message delivery
*/
public subscribeQueue(queue: sqs.IQueue): Subscription {
public subscribeQueue(queue: sqs.IQueue, rawMessageDelivery?: boolean): Subscription {
if (!cdk.Construct.isConstruct(queue)) {
throw new Error(`The supplied Queue object must be an instance of Construct`);
}
Expand All @@ -151,7 +153,8 @@ export abstract class TopicBase extends cdk.Construct implements ITopic {
const sub = new Subscription(queue, subscriptionName, {
topic: this,
endpoint: queue.queueArn,
protocol: SubscriptionProtocol.Sqs
protocol: SubscriptionProtocol.Sqs,
rawMessageDelivery,
});

// add a statement to the queue resource policy which allows this topic
Expand Down Expand Up @@ -190,7 +193,7 @@ export abstract class TopicBase extends cdk.Construct implements ITopic {
const sub = new Subscription(lambdaFunction, subscriptionName, {
topic: this,
endpoint: lambdaFunction.functionArn,
protocol: SubscriptionProtocol.Lambda
protocol: SubscriptionProtocol.Lambda,
});

lambdaFunction.addPermission(this.node.id, {
Expand All @@ -206,7 +209,7 @@ export abstract class TopicBase extends cdk.Construct implements ITopic {
*
* @param name A name for the subscription
* @param emailAddress The email address to use.
* @param jsonFormat True if the email content should be in JSON format (default is false).
* @param options Options for the email delivery format.
*/
public subscribeEmail(name: string, emailAddress: string, options?: EmailSubscriptionOptions): Subscription {
const protocol = (options && options.json ? SubscriptionProtocol.EmailJson : SubscriptionProtocol.Email);
Expand All @@ -223,8 +226,9 @@ export abstract class TopicBase extends cdk.Construct implements ITopic {
*
* @param name A name for the subscription
* @param url The URL to invoke
* @param rawMessageDelivery Enable raw message delivery
*/
public subscribeUrl(name: string, url: string): Subscription {
public subscribeUrl(name: string, url: string, rawMessageDelivery?: boolean): Subscription {
if (!url.startsWith('http://') && !url.startsWith('https://')) {
throw new Error('URL must start with either http:// or https://');
}
Expand All @@ -234,7 +238,8 @@ export abstract class TopicBase extends cdk.Construct implements ITopic {
return new Subscription(this, name, {
topic: this,
endpoint: url,
protocol
protocol,
rawMessageDelivery,
});
}

Expand Down Expand Up @@ -353,5 +358,5 @@ export interface EmailSubscriptionOptions {
*
* @default Message text (false)
*/
json?: boolean
json?: boolean;
}
74 changes: 74 additions & 0 deletions packages/@aws-cdk/aws-sns/test/test.sns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,40 @@ export = {
test.done();
},

'url subscription (with raw delivery)'(test: Test) {
const stack = new cdk.Stack();

const topic = new sns.Topic(stack, 'MyTopic', {
topicName: 'topicName',
displayName: 'displayName'
});

topic.subscribeUrl('appsubscription', 'https://foobar.com/', true);

expect(stack).toMatch({
"Resources": {
"MyTopic86869434": {
"Type": "AWS::SNS::Topic",
"Properties": {
"DisplayName": "displayName",
"TopicName": "topicName"
}
},
"MyTopicappsubscription00FA69EA": {
"Type": "AWS::SNS::Subscription",
"Properties": {
"Endpoint": "https://foobar.com/",
"Protocol": "https",
"TopicArn": { "Ref": "MyTopic86869434" },
"RawMessageDelivery": true
}
}
}
});

test.done();
},

'queue subscription'(test: Test) {
const stack = new cdk.Stack();

Expand Down Expand Up @@ -208,6 +242,35 @@ export = {
test.done();
},

'queue subscription (with raw delivery)'(test: Test) {
const stack = new cdk.Stack();

const topic = new sns.Topic(stack, 'MyTopic', {
topicName: 'topicName',
displayName: 'displayName'
});

const queue = new sqs.Queue(stack, 'MyQueue');

topic.subscribeQueue(queue, true);

expect(stack).to(haveResource('AWS::SNS::Subscription', {
"Endpoint": {
"Fn::GetAtt": [
"MyQueueE6CA6235",
"Arn"
]
},
"Protocol": "sqs",
"TopicArn": {
"Ref": "MyTopic86869434"
},
"RawMessageDelivery": true
}));

test.done();
},

'lambda subscription'(test: Test) {
const stack = new cdk.Stack();

Expand Down Expand Up @@ -504,6 +567,17 @@ export = {

test.done();
},

'invalid use of raw message delivery'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
const topic = new sns.Topic(stack, 'Topic');

// THEN
test.throws(() => topic.subscribe('Nope', 'endpoint://location', sns.SubscriptionProtocol.Application, true),
/Raw message delivery can only be enabled for HTTP\/S and SQS subscriptions/);
test.done();
}
},

'can add a policy to the topic'(test: Test) {
Expand Down