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(apigatewayv2): allow websockets routes to return response to client #22984

Merged
merged 10 commits into from
Feb 18, 2023
17 changes: 16 additions & 1 deletion packages/@aws-cdk/aws-apigatewayv2/lib/websocket/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Resource } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { CfnRoute } from '../apigatewayv2.generated';
import { CfnRoute, CfnRouteResponse } from '../apigatewayv2.generated';
import { IRoute } from '../common';
import { IWebSocketApi } from './api';
import { IWebSocketRouteAuthorizer, WebSocketNoneAuthorizer } from './authorizer';
Expand Down Expand Up @@ -37,6 +37,13 @@ export interface WebSocketRouteOptions {
* @default - No Authorizer
*/
readonly authorizer?: IWebSocketRouteAuthorizer;

/**
* Should the route send a response to the client
* @default false
*/
readonly shouldReturnResponse?: boolean;
emilrowland marked this conversation as resolved.
Show resolved Hide resolved

}

/**
Expand Down Expand Up @@ -102,7 +109,15 @@ export class WebSocketRoute extends Resource implements IWebSocketRoute {
target: `integrations/${config.integrationId}`,
authorizerId: authBindResult.authorizerId,
authorizationType: authBindResult.authorizationType,
routeResponseSelectionExpression: props.shouldReturnResponse ? '$default' : undefined,
});
this.routeId = route.ref;
if (props.shouldReturnResponse) {
new CfnRouteResponse(this, 'Response', {
apiId: props.webSocketApi.apiId,
routeId: route.ref,
routeResponseKey: '$default',
});
}
}
}
22 changes: 22 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,28 @@ describe('WebSocketApi', () => {
});
});

test('addRoute: adds a route with passed key and allows it to return a response', () => {
// GIVEN
const stack = new Stack();
const api = new WebSocketApi(stack, 'api');

// WHEN
const route = api.addRoute('myroute', { integration: new DummyIntegration(), shouldReturnResponse: true });

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', {
ApiId: stack.resolve(api.apiId),
RouteKey: 'myroute',
RouteResponseSelectionExpression: '$default',
});

Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::RouteResponse', {
ApiId: stack.resolve(api.apiId),
RouteId: stack.resolve(route.routeId),
RouteResponseKey: '$default',
});
});

test('connectRouteOptions: adds a $connect route', () => {
// GIVEN
const stack = new Stack();
Expand Down
44 changes: 44 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2/test/websocket/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,50 @@ describe('WebSocketRoute', () => {

Template.fromStack(stack).hasResource('AWS::ApiGatewayV2::Integration', 2);
});

test('default RouteResponseSelectionExpression is set if route will return a response to the client', () => {
// GIVEN
const stack = new Stack();
const webSocketApi = new WebSocketApi(stack, 'Api');

// WHEN
const route = new WebSocketRoute(stack, 'Route', {
webSocketApi,
integration: new DummyIntegration(),
routeKey: 'message',
shouldReturnResponse: true,
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Route', {
ApiId: stack.resolve(webSocketApi.apiId),
RouteKey: 'message',
RouteResponseSelectionExpression: '$default',
Target: {
'Fn::Join': [
'',
[
'integrations/',
{
Ref: 'RouteDummyIntegrationE40E82B4',
},
],
],
},
});

Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::RouteResponse', {
ApiId: stack.resolve(webSocketApi.apiId),
RouteId: stack.resolve(route.routeId),
RouteResponseKey: '$default',
});

Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', {
ApiId: stack.resolve(webSocketApi.apiId),
IntegrationType: 'AWS_PROXY',
IntegrationUri: 'some-uri',
});
});
});


Expand Down