Skip to content

Commit

Permalink
feat(apigateway): auto-create RequestValidator from options to addMet…
Browse files Browse the repository at this point in the history
…hod() (#6780)

closes #6193
  • Loading branch information
nirvana124 authored Apr 1, 2020
1 parent fbc1df3 commit 573464d
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 9 deletions.
16 changes: 9 additions & 7 deletions packages/@aws-cdk/aws-apigateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,18 +297,17 @@ const errorResponseModel = api.addModel('ErrorResponseModel', {
And reference all on your method definition.

```ts
// If you want to define parameter mappings for the request, you need a validator
const validator = api.addRequestValidator('DefaultValidator', {
validateRequestBody: false,
validateRequestParameters: true
});
resource.addMethod('GET', integration, {
// We can mark the parameters as required
requestParameters: {
'method.request.querystring.who': true
},
// We need to set the validator for ensuring they are passed
requestValidator: validator,
// we can set request validator options like below
requestValidatorOptions: {
requestValidatorName: 'test-validator',
validateRequestBody: true,
validateRequestParameters: false
}
methodResponses: [
{
// Successful response from the integration
Expand Down Expand Up @@ -340,6 +339,9 @@ resource.addMethod('GET', integration, {
});
```

Specifying `requestValidatorOptions` automatically creates the RequestValidator construct with the given options.
However, if you have your RequestValidator already initialized or imported, use the `requestValidator` option instead.

#### Default Integration and Method Options

The `defaultIntegration` and `defaultMethodOptions` properties can be used to
Expand Down
27 changes: 25 additions & 2 deletions packages/@aws-cdk/aws-apigateway/lib/method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ConnectionType, Integration } from './integration';
import { MockIntegration } from './integrations/mock';
import { MethodResponse } from './methodresponse';
import { IModel } from './model';
import { IRequestValidator } from './requestvalidator';
import { IRequestValidator, RequestValidatorOptions } from './requestvalidator';
import { IResource } from './resource';
import { RestApi } from './restapi';
import { validateHttpMethod } from './util';
Expand Down Expand Up @@ -73,6 +73,8 @@ export interface MethodOptions {

/**
* The ID of the associated request validator.
* Only one of `requestValidator` or `requestValidatorOptions` must be specified.
* @default - No default validator
*/
readonly requestValidator?: IRequestValidator;

Expand All @@ -83,6 +85,13 @@ export interface MethodOptions {
* @default - no authorization scopes
*/
readonly authorizationScopes?: string[]

/**
* Request validator options to create new validator
* Only one of `requestValidator` or `requestValidatorOptions` must be specified.
* @default - No default validator
*/
readonly requestValidatorOptions?: RequestValidatorOptions;
}

export interface MethodProps {
Expand Down Expand Up @@ -160,7 +169,7 @@ export class Method extends Resource {
integration: this.renderIntegration(props.integration),
methodResponses: this.renderMethodResponses(options.methodResponses),
requestModels: this.renderRequestModels(options.requestModels),
requestValidatorId: options.requestValidator ? options.requestValidator.requestValidatorId : undefined,
requestValidatorId: this.requestValidatorId(options),
authorizationScopes: options.authorizationScopes ?? defaultMethodOptions.authorizationScopes,
};

Expand Down Expand Up @@ -302,6 +311,20 @@ export class Method extends Resource {

return models;
}

private requestValidatorId(options: MethodOptions): string | undefined {
if (options.requestValidator && options.requestValidatorOptions) {
throw new Error(`Only one of 'requestValidator' or 'requestValidatorOptions' must be specified.`);
}

if (options.requestValidatorOptions) {
const validator = this.restApi.addRequestValidator('validator', options.requestValidatorOptions);
return validator.requestValidatorId;
}

// For backward compatibility
return options.requestValidator?.requestValidatorId;
}
}

export enum AuthorizationType {
Expand Down
78 changes: 78 additions & 0 deletions packages/@aws-cdk/aws-apigateway/test/test.method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,84 @@ export = {
AuthorizationScopes: ABSENT
}));

test.done();
},

'method has a request validator with provided properties'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
const api = new apigw.RestApi(stack, 'test-api', { deploy: false });

// WHEN
new apigw.Method(stack, 'method-man', {
httpMethod: 'GET',
resource: api.root,
options: {
requestValidatorOptions: {
requestValidatorName: 'test-validator',
validateRequestBody: true,
validateRequestParameters: false
}
}
});

// THEN
expect(stack).to(haveResource('AWS::ApiGateway::RequestValidator', {
RestApiId: stack.resolve(api.restApiId),
ValidateRequestBody: true,
ValidateRequestParameters: false,
Name: 'test-validator'
}));

test.done();
},

'method does not have a request validator'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
const api = new apigw.RestApi(stack, 'test-api', { deploy: false });

// WHEN
new apigw.Method(stack, 'method-man', {
httpMethod: 'GET',
resource: api.root
});

// THEN
expect(stack).to(haveResource('AWS::ApiGateway::Method', {
RequestValidatorId: ABSENT
}));

test.done();
},

'method does not support both request validator and request validator options'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
const api = new apigw.RestApi(stack, 'test-api', { deploy: false });
const validator = api.addRequestValidator('test-validator1', {
validateRequestBody: true,
validateRequestParameters: false
});

// WHEN
const methodProps = {
httpMethod: 'GET',
resource: api.root,
options: {
requestValidatorOptions: {
requestValidatorName: 'test-validator2',
validateRequestBody: true,
validateRequestParameters: false
},
requestValidator: validator
}
};

// THEN
test.throws(() => new apigw.Method(stack, 'method', methodProps),
/Only one of 'requestValidator' or 'requestValidatorOptions' must be specified./);

test.done();
}
};

0 comments on commit 573464d

Please sign in to comment.