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

Add some documentation around the referencing default Empty/Error models.

Edit documentation around the referencing default Empty/Error models.

Edit documentation around the referencing default Empty/Error models.

Fix 'trailing whitespace' in comments
  • Loading branch information
john-shaskin authored and John Shaskin committed Feb 6, 2019
1 parent bfa40b1 commit c9a77f5
Show file tree
Hide file tree
Showing 5 changed files with 186 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 };
}
46 changes: 46 additions & 0 deletions packages/@aws-cdk/aws-apigateway/lib/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
export interface IModel {
readonly modelId: string;
}

/**
* Represents a reference to a REST API's Empty model, which is available
* as part of the model collection by default. This can be used for mapping
* JSON responses from an integration to what is returned to a client,
* where strong typing is not required. In the absence of any defined
* model, the Empty model will be used to return the response payload
* unmapped.
*
* Definition
* {
* "$schema" : "http://json-schema.org/draft-04/schema#",
* "title" : "Empty Schema",
* "type" : "object"
* }
*
* @see https://docs.amazonaws.cn/en_us/apigateway/latest/developerguide/models-mappings.html#models-mappings-models
*/
export class EmptyModel implements IModel {
public readonly modelId = 'Empty';
}

/**
* Represents a reference to a REST API's Error model, which is available
* as part of the model collection by default. This can be used for mapping
* error JSON responses from an integration to a client, where a simple
* generic message field is sufficient to map and return an error payload.
*
* Definition
* {
* "$schema" : "http://json-schema.org/draft-04/schema#",
* "title" : "Error Schema",
* "type" : "object",
* "properties" : {
* "message" : { "type" : "string" }
* }
* }
*/
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 c9a77f5

Please sign in to comment.