Skip to content

Commit

Permalink
Convert MethodResponse to a class, to enable an API allowing content …
Browse files Browse the repository at this point in the history
…type to be inferred from a created model.

Fix methodresponse usage in README, and update formatting of integration test expected files.

Convert JsonSchemaSchema enum to a static class, to fix build errors.
  • Loading branch information
john-shaskin committed Apr 2, 2019
1 parent b1bdb3d commit abfb8a9
Show file tree
Hide file tree
Showing 13 changed files with 398 additions and 179 deletions.
19 changes: 10 additions & 9 deletions packages/@aws-cdk/aws-apigateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ REST API as follows:
const beerModel = api.addModel('Beer', {
contentType: 'application/json',
schema: {
$schema: 'http://json-schema.org/draft-04/schema#',
$schema: JsonSchemaSchema.Draft4,
title: 'Beer',
type: 'object',
properties: {
Expand All @@ -177,7 +177,7 @@ const breweryModel = new apiGateway.Model(this, 'breweryModel', {
description: 'Simple model for defining a brewery.',
contentType: 'application/json',
schema: {
$schema: 'http://json-schema.org/draft-04/schema#',
$schema: JsonSchemaSchema.Draft4,
title: 'Brewery',
type: 'object',
properties: {
Expand All @@ -200,13 +200,14 @@ RequestModel support not yet implemented.

```ts
const method = api.beer.addMethod('GET', getBeerLambdaHandler, {
methodResponses: [{
statusCode: '200',
responseModels: {
'application/json': beerModelJson,
'application/xml': beerModelXml,
}
}]
methodResponses: [
new MethodResponse({ statusCode: '200' })
.addResponseModel(beerModelJson)
.addResonseModel(beerModelXml),
new MethodResponse({ statusCode: '400' })
.addResponseModel(errorModelJson)
.addResonseModel(errorModelXml),
]
});
```

Expand Down
14 changes: 14 additions & 0 deletions packages/@aws-cdk/aws-apigateway/lib/json-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,18 @@ export class JsonSchemaMapper {
}

private static readonly PropsWithPrefix = ['schema', 'ref'];
}

export class JsonSchemaSchema {
public static get draft4(): string {
return JsonSchemaSchema.schemaUrlTemplate('draft-04');
}

public static get draft7(): string {
return JsonSchemaSchema.schemaUrlTemplate('draft-07');
}

public static schemaUrlTemplate(draft: string): string {
return `http://json-schema.org/${draft}/schema#`;
}
}
6 changes: 3 additions & 3 deletions packages/@aws-cdk/aws-apigateway/lib/method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +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 { IMethodResponse } from './methodresponse';
import { IRestApiResource } from './resource';
import { RestApi } from './restapi';
import { validateHttpMethod } from './util';
Expand Down Expand Up @@ -44,7 +44,7 @@ export interface MethodOptions {
* 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
*/
readonly methodResponses?: MethodResponse[]
readonly methodResponses?: IMethodResponse[]

/**
* The request parameters that API Gateway accepts. Specify request parameters
Expand Down Expand Up @@ -209,7 +209,7 @@ export class Method extends cdk.Construct {
};
}

private renderMethodResponses(methodResponses: MethodResponse[] | undefined): CfnMethod.MethodResponseProperty[] | undefined {
private renderMethodResponses(methodResponses: IMethodResponse[] | undefined): CfnMethod.MethodResponseProperty[] | undefined {
if (!methodResponses) {
// Fall back to nothing
return undefined;
Expand Down
43 changes: 41 additions & 2 deletions packages/@aws-cdk/aws-apigateway/lib/methodresponse.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IModelRef } from './model';
import { IModelRef, Model } from './model';

export interface MethodResponse {
export interface IMethodResponse {

/**
* The method response's status code, which you map to an IntegrationResponse.
Expand All @@ -25,4 +25,43 @@ export interface MethodResponse {
* @default None
*/
readonly responseModels?: { [contentType: string]: IModelRef };
}

export interface MethodResponseProps {
readonly statusCode: string;
readonly responseParameters?: { [destination: string]: boolean };
readonly responseModels?: { [contentType: string]: IModelRef };
}

export class MethodResponse implements IMethodResponse {
public readonly statusCode: string;
public readonly responseParameters?: { [destination: string]: boolean };
private responseModelsInt?: { [contentType: string]: IModelRef };

public get responseModels(): { [contentType: string]: IModelRef } | undefined {
return this.responseModelsInt;
}

constructor(props: MethodResponseProps) {
this.statusCode = props.statusCode;
this.responseParameters = props.responseParameters;
this.responseModelsInt = props.responseModels;
}

public addResponseModelForContentType(contentType: string, model: IModelRef) {
if (!this.responseModelsInt) {
this.responseModelsInt = {};
}

if (this.responseModelsInt[contentType]) {
throw new Error(`A model has already been registered for the content type ${contentType}`);
}
this.responseModelsInt[contentType] = model;

return this;
}

public addResponseModel(model: Model): MethodResponse {
return this.addResponseModelForContentType(model.contentType, model);
}
}
6 changes: 6 additions & 0 deletions packages/@aws-cdk/aws-apigateway/lib/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ export class Model extends cdk.Construct implements IModel {
*/
public readonly restApi: IRestApi;

/**
* The content type for the model.
*/
public readonly contentType: string;

constructor(scope: cdk.Construct, id: string, props: ModelProps) {
super(scope, id);

Expand All @@ -157,6 +162,7 @@ export class Model extends cdk.Construct implements IModel {

this.modelId = model.ref;
this.restApi = props.restApi;
this.contentType = props.contentType;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,7 @@
"Effect": "Allow",
"Principal": {
"Service": {
"Fn::Join":
[
"Fn::Join": [
"",
[
"lambda.",
Expand Down Expand Up @@ -287,7 +286,7 @@
"Type": "AWS::ApiGateway::Deployment",
"Properties": {
"RestApiId": {
"Ref": "beerapi67AE41CF"
"Ref": "beerapi67AE41CF"
},
"Description": "Automatically created by the RestApi construct"
},
Expand All @@ -302,17 +301,17 @@
"Type": "AWS::ApiGateway::Stage",
"Properties": {
"RestApiId": {
"Ref": "beerapi67AE41CF"
"Ref": "beerapi67AE41CF"
},
"DeploymentId": {
"Ref": "beerapiDeployment3077C14B2cae185d40ed71262560f2f6141fd859"
"Ref": "beerapiDeployment3077C14B2cae185d40ed71262560f2f6141fd859"
},
"StageName": "prod"
}
},
"beerapiCloudWatchRole81F996BB": {
"Type": "AWS::IAM::Role",
"Properties": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
Expand Down Expand Up @@ -366,8 +365,8 @@
]
},
"beerapibeerCF23738E": {
"Type": "AWS::ApiGateway::Resource",
"Properties": {
"Type": "AWS::ApiGateway::Resource",
"Properties": {
"ParentId": {
"Fn::GetAtt": [
"beerapi67AE41CF",
Expand All @@ -376,7 +375,7 @@
},
"PathPart": "beer",
"RestApiId": {
"Ref": "beerapi67AE41CF"
"Ref": "beerapi67AE41CF"
}
}
},
Expand Down Expand Up @@ -407,7 +406,7 @@
"Ref": "AWS::Region"
},
":lambda:path/2015-03-31/functions/",
{
{
"Fn::GetAtt": [
"BeersHandlerA9F3A7B5",
"Arn"
Expand All @@ -421,9 +420,9 @@
"MethodResponses": [
{
"ResponseModels": {
"application/json": {
"Ref": "beerapiBeerSummaryModel1EE635AB"
}
"application/json": {
"Ref": "beerapiBeerSummaryModel1EE635AB"
}
},
"StatusCode": "200"
}
Expand All @@ -446,10 +445,10 @@
"Type": "AWS::ApiGateway::Method",
"Properties": {
"HttpMethod": "GET",
"ResourceId":{
"ResourceId": {
"Ref": "beerapibeerbeerid64F377BE"
},
"RestApiId":{
"RestApiId": {
"Ref": "beerapi67AE41CF"
},
"AuthorizationType": "NONE",
Expand Down Expand Up @@ -482,10 +481,10 @@
},
"MethodResponses": [
{
"ResponseModels":{
"application/json": {
"Ref": "beerapiBeerDetailsModel5D942EB5"
}
"ResponseModels": {
"application/json": {
"Ref": "beerapiBeerDetailsModel5D942EB5"
}
},
"StatusCode": "200"
}
Expand All @@ -495,8 +494,8 @@
"beerapiBeerSummaryModel1EE635AB": {
"Type": "AWS::ApiGateway::Model",
"Properties": {
"RestApiId":{
"Ref": "beerapi67AE41CF"
"RestApiId": {
"Ref": "beerapi67AE41CF"
},
"ContentType": "application/json",
"Description": "A basic summary for a beer. Used for listing a bunch of beers at a glance.",
Expand All @@ -506,8 +505,12 @@
"title": "BeerSummary",
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" }
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
}
Expand All @@ -526,9 +529,15 @@
"title": "Brewery",
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"address": { "type": "string" },
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"address": {
"type": "string"
},
"beers": {
"type": "array",
"items": {
Expand Down Expand Up @@ -571,33 +580,43 @@
"title": "Beer",
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"brewery": {
"type": "object",
"$ref": {
"Fn::Join": [
"",
[
"https://apigateway.",
{
"Ref": "AWS::URLSuffix"
},
"/restapis/",
{
"Ref": "beerapi67AE41CF"
},
"/models/",
{
"Ref": "beerapiBreweryModelA8E987E0"
}
]
"Fn::Join": [
"",
[
"https://apigateway.",
{
"Ref": "AWS::URLSuffix"
},
"/restapis/",
{
"Ref": "beerapi67AE41CF"
},
"/models/",
{
"Ref": "beerapiBreweryModelA8E987E0"
}
]
}
]
}
},
"style": {
"type": "string"
},
"style": { "type": "string" },
"abv": { "type": "number" },
"ibu": { "type": "number"}
"abv": {
"type": "number"
},
"ibu": {
"type": "number"
}
}
}
}
Expand Down
Loading

0 comments on commit abfb8a9

Please sign in to comment.