Skip to content

Commit

Permalink
Add support for MethodResponse to aws-apigateway.
Browse files Browse the repository at this point in the history
Remove Dockerfile that was no longer needed

Update python base image from 3.6 to 3.6.5

Make the dockerfile work

Add MethodResponse support for aws-apigateway

Remove Dockerfile that was no longer needed

Update python base image from 3.6 to 3.6.5

Make the dockerfile work

Add MethodResponse to API Gateway Method.

Add some documentation to the MethodResponse properties. Update the test for MethodResponse with response models.

Fix some formatting and finish adding code documentation for MethodResponse.

Remove Dockerfile from this branch

Fix bad merge to methodresponse test.

Correct the MethodResponse response models documentation.

Add IModel type to reference when configuring a MethodResponse

Slight update to comments.

Update API Gateway MethodResponse documentation.

Author:    John Shaskin <guitarjohnn@gmail.com>
Date:      Mon Feb 05 5:30:45 2019 +0100
  • Loading branch information
john-shaskin committed Feb 5, 2019
1 parent 299fb6a commit be86fed
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 5 deletions.
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-apigateway/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export * from './stage';
export * from './integrations';
export * from './lambda-api';
export * from './vpc-link';
export * from './methodresponse';
export * from './model';

// AWS::ApiGateway CloudFormation Resources:
export * from './apigateway.generated';
56 changes: 52 additions & 4 deletions packages/@aws-cdk/aws-apigateway/lib/method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import cdk = require('@aws-cdk/cdk');
import { CfnMethod, CfnMethodProps } from './apigateway.generated';
import { ConnectionType, Integration } from './integration';
import { MockIntegration } from './integrations/mock';
import { MethodResponse } from './methodresponse';
import { IRestApiResource } from './resource';
import { RestApi } from './restapi';
import { validateHttpMethod } from './util';
Expand Down Expand Up @@ -34,12 +35,30 @@ export interface MethodOptions {
*/
apiKeyRequired?: boolean;

/**
* The responses that can be sent to the client who calls the method.
* @default None
*
* This property is not required, but if these are not supplied for a Lambda
* proxy integration, the Lambda function must return a value of the correct format,
* for the integration response to be correctly mapped to a response to the client.
* @see https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-method-settings-method-response.html
*/
methodResponses?: MethodResponse[]

/**
* The request parameters that API Gateway accepts. Specify request parameters
* as key-value pairs (string-to-Boolean mapping), with a source as the key and
* a Boolean as the value. The Boolean specifies whether a parameter is required.
* A source must match the format method.request.location.name, where the location
* is querystring, path, or header, and name is a valid, unique parameter name.
* @default None
*/
requestParameters?: { [param: string]: boolean };

// TODO:
// - RequestValidatorId
// - RequestModels
// - RequestParameters
// - MethodResponses
requestParameters?: { [param: string]: boolean };
}

export interface MethodProps {
Expand Down Expand Up @@ -93,7 +112,8 @@ export class Method extends cdk.Construct {
authorizationType: options.authorizationType || defaultMethodOptions.authorizationType || AuthorizationType.None,
authorizerId: options.authorizerId || defaultMethodOptions.authorizerId,
requestParameters: options.requestParameters,
integration: this.renderIntegration(props.integration)
integration: this.renderIntegration(props.integration),
methodResponses: this.renderMethodResponses(options.methodResponses),
};

const resource = new CfnMethod(this, 'Resource', methodProps);
Expand Down Expand Up @@ -188,6 +208,34 @@ export class Method extends cdk.Construct {
credentials,
};
}

private renderMethodResponses(methodResponses: MethodResponse[] | undefined): CfnMethod.MethodResponseProperty[] | undefined {
if (!methodResponses) {
// Fall back to nothing
return undefined;
}

return methodResponses.map(mr => {
let responseModels: {[contentType: string]: string} | undefined;

if (mr.responseModels) {
responseModels = {};
for (const contentType in mr.responseModels) {
if (mr.responseModels.hasOwnProperty(contentType)) {
responseModels[contentType] = mr.responseModels[contentType].modelId;
}
}
}

const methodResponseProp = {
statusCode: mr.statusCode,
responseParameters: mr.responseParameters,
responseModels,
};

return methodResponseProp;
});
}
}

export enum AuthorizationType {
Expand Down
28 changes: 28 additions & 0 deletions packages/@aws-cdk/aws-apigateway/lib/methodresponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { IModel } from './model';

export interface MethodResponse {

/**
* The method response's status code, which you map to an IntegrationResponse.
* Required.
*/
statusCode: string;

/**
* Response parameters that API Gateway sends to the client that called a method.
* Specify response parameters as key-value pairs (string-to-Boolean maps), with
* a destination as the key and a Boolean as the value. Specify the destination
* using the following pattern: method.response.header.name, where the name is a
* valid, unique header name. The Boolean specifies whether a parameter is required.
* @default None
*/
responseParameters?: { [destination: string]: boolean };

/**
* The resources used for the response's content type. Specify response models as
* key-value pairs (string-to-string maps), with a content type as the key and a Model
* resource name as the value.
* @default None
*/
responseModels?: { [contentType: string]: IModel };
}
13 changes: 13 additions & 0 deletions packages/@aws-cdk/aws-apigateway/lib/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export interface IModel {
readonly modelId: string;
}

export class EmptyModel implements IModel {
public readonly modelId = 'Empty';
}

export class ErrorModel implements IModel {
public readonly modelId = 'Error';
}

// TODO: Implement Model, enabling management of custom models.
59 changes: 58 additions & 1 deletion packages/@aws-cdk/aws-apigateway/test/test.method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import iam = require('@aws-cdk/aws-iam');
import cdk = require('@aws-cdk/cdk');
import { Test } from 'nodeunit';
import apigateway = require('../lib');
import { ConnectionType } from '../lib';
import { ConnectionType, EmptyModel, ErrorModel } from '../lib';

export = {
'default setup'(test: Test) {
Expand Down Expand Up @@ -304,6 +304,63 @@ export = {
test.done();
},

'methodResponse set one or more method responses via options'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
const api = new apigateway.RestApi(stack, 'test-api', { deploy: false });

// WHEN
new apigateway.Method(stack, 'method-man', {
httpMethod: 'GET',
resource: api.root,
options: {
methodResponses: [{
statusCode: '200'
}, {
statusCode: "400",
responseParameters: {
'method.response.header.killerbees': false
}
}, {
statusCode: "500",
responseParameters: {
'method.response.header.errthing': true
},
responseModels: {
'application/json': new EmptyModel(),
'text/plain': new ErrorModel()
}
}
]
}
});

// THEN
expect(stack).to(haveResource('AWS::ApiGateway::Method', {
HttpMethod: 'GET',
MethodResponses: [{
StatusCode: "200"
}, {
StatusCode: "400",
ResponseParameters: {
'method.response.header.killerbees': false
}
}, {
StatusCode: "500",
ResponseParameters: {
'method.response.header.errthing': true
},
ResponseModels: {
'application/json': 'Empty',
'text/plain': 'Error'
}
}
]
}));

test.done();
},

'multiple integration responses can be used'(test: Test) { // @see https://github.com/awslabs/aws-cdk/issues/1608
// GIVEN
const stack = new cdk.Stack();
Expand Down

0 comments on commit be86fed

Please sign in to comment.