diff --git a/packages/@aws-cdk/aws-apigateway/README.md b/packages/@aws-cdk/aws-apigateway/README.md index caf528f70dff6..d9af6450d40a0 100644 --- a/packages/@aws-cdk/aws-apigateway/README.md +++ b/packages/@aws-cdk/aws-apigateway/README.md @@ -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: { @@ -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: { @@ -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), + ] }); ``` diff --git a/packages/@aws-cdk/aws-apigateway/lib/json-schema.ts b/packages/@aws-cdk/aws-apigateway/lib/json-schema.ts index fa713ca20d14a..e5115a8062e82 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/json-schema.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/json-schema.ts @@ -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#`; + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/lib/method.ts b/packages/@aws-cdk/aws-apigateway/lib/method.ts index e492cb573c722..af14dd54f6914 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/method.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/method.ts @@ -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'; @@ -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 @@ -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; diff --git a/packages/@aws-cdk/aws-apigateway/lib/methodresponse.ts b/packages/@aws-cdk/aws-apigateway/lib/methodresponse.ts index e963a80f2ad25..40f0c8cc8d143 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/methodresponse.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/methodresponse.ts @@ -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. @@ -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); + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/lib/model.ts b/packages/@aws-cdk/aws-apigateway/lib/model.ts index 88246c9138892..479337328fbf6 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/model.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/model.ts @@ -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); @@ -157,6 +162,7 @@ export class Model extends cdk.Construct implements IModel { this.modelId = model.ref; this.restApi = props.restApi; + this.contentType = props.contentType; } /** diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi-model.beer.expected.json b/packages/@aws-cdk/aws-apigateway/test/integ.restapi-model.beer.expected.json index 470c2ef5eae63..4254fdc596c2a 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi-model.beer.expected.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi-model.beer.expected.json @@ -148,8 +148,7 @@ "Effect": "Allow", "Principal": { "Service": { - "Fn::Join": - [ + "Fn::Join": [ "", [ "lambda.", @@ -287,7 +286,7 @@ "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { - "Ref": "beerapi67AE41CF" + "Ref": "beerapi67AE41CF" }, "Description": "Automatically created by the RestApi construct" }, @@ -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": [ { @@ -366,8 +365,8 @@ ] }, "beerapibeerCF23738E": { - "Type": "AWS::ApiGateway::Resource", - "Properties": { + "Type": "AWS::ApiGateway::Resource", + "Properties": { "ParentId": { "Fn::GetAtt": [ "beerapi67AE41CF", @@ -376,7 +375,7 @@ }, "PathPart": "beer", "RestApiId": { - "Ref": "beerapi67AE41CF" + "Ref": "beerapi67AE41CF" } } }, @@ -407,7 +406,7 @@ "Ref": "AWS::Region" }, ":lambda:path/2015-03-31/functions/", - { + { "Fn::GetAtt": [ "BeersHandlerA9F3A7B5", "Arn" @@ -421,9 +420,9 @@ "MethodResponses": [ { "ResponseModels": { - "application/json": { - "Ref": "beerapiBeerSummaryModel1EE635AB" - } + "application/json": { + "Ref": "beerapiBeerSummaryModel1EE635AB" + } }, "StatusCode": "200" } @@ -446,10 +445,10 @@ "Type": "AWS::ApiGateway::Method", "Properties": { "HttpMethod": "GET", - "ResourceId":{ + "ResourceId": { "Ref": "beerapibeerbeerid64F377BE" }, - "RestApiId":{ + "RestApiId": { "Ref": "beerapi67AE41CF" }, "AuthorizationType": "NONE", @@ -482,10 +481,10 @@ }, "MethodResponses": [ { - "ResponseModels":{ - "application/json": { - "Ref": "beerapiBeerDetailsModel5D942EB5" - } + "ResponseModels": { + "application/json": { + "Ref": "beerapiBeerDetailsModel5D942EB5" + } }, "StatusCode": "200" } @@ -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.", @@ -506,8 +505,12 @@ "title": "BeerSummary", "type": "object", "properties": { - "id": { "type": "string" }, - "name": { "type": "string" } + "id": { + "type": "string" + }, + "name": { + "type": "string" + } } } } @@ -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": { @@ -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" + } } } } diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi-model.beer.ts b/packages/@aws-cdk/aws-apigateway/test/integ.restapi-model.beer.ts index 5f9cd624eb129..aadc60d58abb2 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi-model.beer.ts +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi-model.beer.ts @@ -1,133 +1,130 @@ import lambda = require('@aws-cdk/aws-lambda'); import cdk = require('@aws-cdk/cdk'); import apigw = require('../lib'); +import { JsonSchemaSchema, MethodResponse } from '../lib'; class BeerApiStack extends cdk.Stack { - constructor(scope: cdk.App, id: string) { - super(scope, id); + constructor(scope: cdk.App, id: string) { + super(scope, id); - // Lambda handler - const beersHandler = new apigw.LambdaIntegration(new lambda.Function(this, 'BeersHandler', { - runtime: lambda.Runtime.NodeJS610, - handler: 'index.handler', - code: lambda.Code.inline(`exports.handler = ${getAllTheBeersHandler}`) - })); + // Lambda handler + const beersHandler = new apigw.LambdaIntegration(new lambda.Function(this, 'BeersHandler', { + runtime: lambda.Runtime.NodeJS610, + handler: 'index.handler', + code: lambda.Code.inline(`exports.handler = ${getAllTheBeersHandler}`) + })); - const beerHandler = new apigw.LambdaIntegration(new lambda.Function(this, 'BeerHandler', { - runtime: lambda.Runtime.NodeJS610, - handler: 'index.handler', - code: lambda.Code.inline(`exports.handler = ${getTheOneBeerHandler}`) - })); + const beerHandler = new apigw.LambdaIntegration(new lambda.Function(this, 'BeerHandler', { + runtime: lambda.Runtime.NodeJS610, + handler: 'index.handler', + code: lambda.Code.inline(`exports.handler = ${getTheOneBeerHandler}`) + })); - // API + resource - const api = new apigw.RestApi(this, 'beer-api'); + // API + resource + const api = new apigw.RestApi(this, 'beer-api'); - // Models - const beerSummaryModel = api.addModel('BeerSummary', { - contentType: 'application/json', - schema: { - schema: 'http://json-schema.org/draft-04/schema#', - title: 'BeerSummary', - type: 'object', - properties: { - id: { type: 'string' }, - name: { type: 'string' }, - }, - }, - description: 'A basic summary for a beer. Used for listing a bunch of beers at a glance.' - }); + // Models + const beerSummaryModel = api.addModel('BeerSummary', { + contentType: 'application/json', + schema: { + schema: JsonSchemaSchema.draft4, + title: 'BeerSummary', + type: 'object', + properties: { + id: { type: 'string' }, + name: { type: 'string' }, + }, + }, + description: 'A basic summary for a beer. Used for listing a bunch of beers at a glance.' + }); - const breweryModel = api.addModel('Brewery', { - contentType: 'application/json', - schema: { - schema: 'http://json-schema.org/draft-04/schema#', - title: 'Brewery', - type: 'object', - properties: { - id: { type: 'string' }, - name: { type: 'string' }, - address: { type: 'string' }, - beers: { type: 'array', items: { ref: beerSummaryModel.referenceForSchema } }, - }, - }, - description: 'Models a brewery.', - }); + const breweryModel = api.addModel('Brewery', { + contentType: 'application/json', + schema: { + schema: JsonSchemaSchema.draft4, + title: 'Brewery', + type: 'object', + properties: { + id: { type: 'string' }, + name: { type: 'string' }, + address: { type: 'string' }, + beers: { type: 'array', items: { ref: beerSummaryModel.referenceForSchema } }, + }, + }, + description: 'Models a brewery.', + }); - const beerDetailsModel = api.addModel('BeerDetails', { - contentType: 'application/json', - schema: { - schema: 'http://json-schema.org/draft-04/schema#', - title: 'Beer', - type: 'object', - properties: { - id: { type: 'string' }, - name: { type: 'string' }, - brewery: { type: 'object', ref: breweryModel.referenceForSchema }, - style: { type: 'string' }, - abv: { type: 'number' }, - ibu: { type: 'number' }, - }, - }, - description: 'Models details of an individual beer.', - }); + const beerDetailsModel = api.addModel('BeerDetails', { + contentType: 'application/json', + schema: { + schema: JsonSchemaSchema.draft4, + title: 'Beer', + type: 'object', + properties: { + id: { type: 'string' }, + name: { type: 'string' }, + brewery: { type: 'object', ref: breweryModel.referenceForSchema }, + style: { type: 'string' }, + abv: { type: 'number' }, + ibu: { type: 'number' }, + }, + }, + description: 'Models details of an individual beer.', + }); - // Resources and methods - const resourceBeers = api.root.addResource('beer'); - resourceBeers.addMethod('GET', beersHandler, { - methodResponses: [{ - statusCode: '200', - responseModels: { - 'application/json': beerSummaryModel, - } - }] - }); + // Resources and methods + const resourceBeers = api.root.addResource('beer'); + resourceBeers.addMethod('GET', beersHandler, { + methodResponses: [ + new MethodResponse({ statusCode: '200' }) + .addResponseModel(beerSummaryModel) + ] + }); - const resourceBeer = resourceBeers.addResource('{beer_id}'); - resourceBeer.addMethod('GET', beerHandler, { - methodResponses: [{ - statusCode: '200', - responseModels: { - 'application/json': beerDetailsModel, - } - }] - }); - } + const resourceBeer = resourceBeers.addResource('{beer_id}'); + resourceBeer.addMethod('GET', beerHandler, { + methodResponses: [ + new MethodResponse({ statusCode: '200' }) + .addResponseModel(beerDetailsModel) + ] + }); + } } class BeerApp extends cdk.App { - constructor() { - super(); + constructor() { + super(); - new BeerApiStack(this, 'restapi-model-beer-example'); - } + new BeerApiStack(this, 'restapi-model-beer-example'); } +} function getAllTheBeersHandler(_event: any, _: any, callback: any) { - callback(undefined, { - isBase64Encoded: false, - statusCode: 200, - headers: { 'content-type': 'application/json' }, - body: JSON.stringify([{ - id: '42095j23095u390j330r93', - name: 'Duff', - }]), - }); + callback(undefined, { + isBase64Encoded: false, + statusCode: 200, + headers: { 'content-type': 'application/json' }, + body: JSON.stringify([{ + id: '42095j23095u390j330r93', + name: 'Duff', + }]), + }); } function getTheOneBeerHandler(_event: any, _: any, callback: any) { - callback(undefined, { - isBase64Encoded: false, - statusCode: 200, - headers: { 'content-type': 'application/json' }, - body: JSON.stringify({ - id: '42095j23095u390j330r93', - name: 'Duff', - brewery: 'Duff Brewing Company', - style: 'American Adjunct Lager', - abv: 4.5, - ibu: 25, - }), - }); + callback(undefined, { + isBase64Encoded: false, + statusCode: 200, + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ + id: '42095j23095u390j330r93', + name: 'Duff', + brewery: 'Duff Brewing Company', + style: 'American Adjunct Lager', + abv: 4.5, + ibu: 25, + }), + }); } new BeerApp().run(); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.books.expected.json b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.books.expected.json index 0baf839a608ca..c74b0616d382a 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.books.expected.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.books.expected.json @@ -920,4 +920,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.expected.json b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.expected.json index c46e8005d766f..3cb1aa79d3fe2 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.expected.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.expected.json @@ -653,4 +653,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/test.json-schema.ts b/packages/@aws-cdk/aws-apigateway/test/test.json-schema.ts index a36ddde0173ed..68113dbb5f4a1 100644 --- a/packages/@aws-cdk/aws-apigateway/test/test.json-schema.ts +++ b/packages/@aws-cdk/aws-apigateway/test/test.json-schema.ts @@ -1,11 +1,11 @@ import { Test } from 'nodeunit'; -import { JsonSchema, JsonSchemaMapper } from '../lib'; +import { JsonSchema, JsonSchemaMapper, JsonSchemaSchema } from '../lib'; export = { 'toCfnJsonSchema adds missing $ character into schema property'(test: Test) { // GIVEN const schema: JsonSchema = { - schema: 'http://json-schema.org/draft-04/schema#', + schema: JsonSchemaSchema.draft4, title: 'This model references Scooby Doo', type: 'object', properties: { @@ -48,7 +48,7 @@ export = { 'toCfnJsonSchema does not accidentally replace ref or schema in schema values'(test: Test) { // GIVEN const schema: JsonSchema = { - schema: 'http://json-schema.org/draft-04/schema#', + schema: JsonSchemaSchema.draft4, title: 'This is a schema full of "ref": fun and also some "schema":', }; diff --git a/packages/@aws-cdk/aws-apigateway/test/test.method.ts b/packages/@aws-cdk/aws-apigateway/test/test.method.ts index b74b6f1241baf..55b42c033090c 100644 --- a/packages/@aws-cdk/aws-apigateway/test/test.method.ts +++ b/packages/@aws-cdk/aws-apigateway/test/test.method.ts @@ -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, EmptyModel, ErrorModel } from '../lib'; +import { ConnectionType, EmptyModel, ErrorModel, JsonSchemaSchema, MethodResponse, Model } from '../lib'; export = { 'default setup'(test: Test) { @@ -361,6 +361,149 @@ export = { test.done(); }, + 'can create methodresponse, matching content type with model'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const api = new apigateway.RestApi(stack, 'test-api', { deploy: false }); + + // WHEN + const universalModel = api.addModel('AnswerToLifeTheUniverseAndEverything', { + contentType: 'application/xml', + schema: { + schema: JsonSchemaSchema.draft4, + title: 'AnswerToLifeTheUniverseAndEverything', + type: 'object', + properties: { + answer: { type: 'integer', minimum: 42, maximum: 42 }, + } + } + }); + const customErrorModel = api.addModel('CustomError', { + contentType: 'application/xml', + schema: { + schema: JsonSchemaSchema.draft4, + title: 'CustomError', + type: 'object', + properties: { + message: { type: 'string' }, + code: { type: 'integer' }, + } + } + }); + const ok200Response = new MethodResponse({ + statusCode: '200', + }).addResponseModel(universalModel); + + const errorResponse = new MethodResponse({ + statusCode: '400', + }).addResponseModel(customErrorModel); + + new apigateway.Method(stack, 'method-man', { + httpMethod: 'GET', + resource: api.root, + options: { + methodResponses: [ + ok200Response, + errorResponse, + ], + }, + }); + + // THEN + expect(stack).to(haveResource('AWS::ApiGateway::Method', { + HttpMethod: 'GET', + MethodResponses: [{ + StatusCode: "200", + ResponseModels: { + 'application/xml': { Ref: 'testapiAnswerToLifeTheUniverseAndEverythingModel48FC957B'} + } + }, { + StatusCode: "400", + ResponseModels: { + 'application/xml': { Ref: 'testapiCustomErrorModel41D1802D'} + } + }, + ] + })); + + test.done(); + }, + + 'can create methodresponse from an imported model with assumed content type'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const api = new apigateway.RestApi(stack, 'test-api', { deploy: false }); + + // WHEN + const importedModel = Model.import(stack, 'imported-model', { modelId: 'something-imported' }); + + new apigateway.Method(stack, 'method-man', { + httpMethod: 'GET', + resource: api.root, + options: { + methodResponses: [ + new MethodResponse({ + statusCode: '200', + }).addResponseModelForContentType('application/json', importedModel) + ], + }, + }); + + // THEN + expect(stack).to(haveResource('AWS::ApiGateway::Method', { + HttpMethod: 'GET', + MethodResponses: [{ + StatusCode: "200", + ResponseModels: { + 'application/json': "something-imported" + } + }, + ] + })); + + test.done(); + }, + + 'throws error if duplicate model added for content type'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const api = new apigateway.RestApi(stack, 'test-api', { deploy: false }); + + // WHEN + const universalModel = api.addModel('AnswerToLifeTheUniverseAndEverything', { + contentType: 'application/xml', + schema: { + schema: JsonSchemaSchema.draft4, + title: 'AnswerToLifeTheUniverseAndEverything', + type: 'object', + properties: { + answer: { type: 'integer', minimum: 42, maximum: 42 }, + } + } + }); + const customErrorModel = api.addModel('CustomError', { + contentType: 'application/xml', + schema: { + schema: JsonSchemaSchema.draft4, + title: 'CustomError', + type: 'object', + properties: { + message: { type: 'string' }, + code: { type: 'integer' }, + } + } + }); + test.throws(() => { + new MethodResponse({ + statusCode: '200', + }) + .addResponseModel(universalModel) + .addResponseModel(customErrorModel); + }); + + 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(); diff --git a/packages/@aws-cdk/aws-apigateway/test/test.model.ts b/packages/@aws-cdk/aws-apigateway/test/test.model.ts index 85072219fbccd..279fc08a43513 100644 --- a/packages/@aws-cdk/aws-apigateway/test/test.model.ts +++ b/packages/@aws-cdk/aws-apigateway/test/test.model.ts @@ -1,7 +1,7 @@ import { expect, haveResource, SynthUtils } from '@aws-cdk/assert'; import cdk = require('@aws-cdk/cdk'); import { Test } from 'nodeunit'; -import { MockIntegration, Model, RestApi } from '../lib'; +import { JsonSchemaSchema, MockIntegration, Model, RestApi } from '../lib'; export = { 'minimal setup'(test: Test) { @@ -30,7 +30,7 @@ export = { // WHEN const schema = { - schema: 'http://json-schema.org/draft-04/schema#', + schema: JsonSchemaSchema.draft4, title: 'ChocolateBars', type: 'array', items: { diff --git a/packages/decdk/package.json b/packages/decdk/package.json index c3fbf21c7cfbb..210a664ad1190 100644 --- a/packages/decdk/package.json +++ b/packages/decdk/package.json @@ -146,4 +146,4 @@ "engines": { "node": ">= 8.10.0" } -} +} \ No newline at end of file