Skip to content

Commit

Permalink
fix(AWS API Gateway): Create one request validator and reuse (#9319)
Browse files Browse the repository at this point in the history
  • Loading branch information
gambit66 committed Apr 22, 2021
1 parent 7e139bb commit 154351f
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 66 deletions.
6 changes: 4 additions & 2 deletions lib/plugins/aws/lib/naming.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,10 @@ module.exports = {
getMethodLogicalId(resourceId, methodName) {
return `ApiGatewayMethod${resourceId}${this.normalizeMethodName(methodName)}`;
},
getValidatorLogicalId(modelLogicalId) {
return `${modelLogicalId}Validator`;
getValidatorLogicalId() {
return `ApiGateway${this.normalizeNameToAlphaNumericOnly(
this.provider.serverless.service.service
)}RequestValidator`;
},
getModelLogicalId(schemaId) {
return `ApiGateway${_.upperFirst(_.camelCase(schemaId))}Model`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,42 @@ module.exports = {
event.http.method
);

let validatorLogicalId;
let validatorName;

if (event.http.request && event.http.request.schemas) {
const template = this.serverless.service.provider.compiledCloudFormationTemplate.Resources[
methodLogicalId
];
for (const [contentType, schemaConfig] of _.entries(event.http.request.schemas)) {
let modelLogicalId;
let validatorLogicalId;

const referencedDefinitionFromProvider =
!_.isObject(schemaConfig) && _.get(apiGatewayConfig, `request.schemas.${schemaConfig}`);

if (!validatorLogicalId) {
const requestValidator = this.createRequestValidator();
validatorLogicalId = requestValidator.validatorLogicalId;
validatorName = requestValidator.validatorName;
}

if (referencedDefinitionFromProvider) {
const models = this.createProviderModel(
modelLogicalId = this.createProviderModel(
schemaConfig,
apiGatewayConfig.request.schemas[schemaConfig]
apiGatewayConfig.request.schemas[schemaConfig],
validatorLogicalId,
validatorName
);
modelLogicalId = models.modelLogicalId;
validatorLogicalId = models.validatorLogicalId;
} else {
// In this situation, we have two options - schema is defined as string that does not reference model from provider or as an object
let modelName;
let description;
let definition;
let validatorName;

if (_.isObject(schemaConfig)) {
if (schemaConfig.schema) {
// In this case, schema is defined as an object with explicit properties
modelName = schemaConfig.name;
validatorName = modelName ? `${modelName}Validator` : null;
description = schemaConfig.description;
definition = schemaConfig.schema;
} else {
Expand All @@ -60,10 +66,6 @@ module.exports = {
contentType
);

validatorLogicalId = this.provider.naming.getValidatorLogicalId(
this.provider.naming.getModelLogicalId(resourceName)
);

Object.assign(
this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
{
Expand All @@ -77,16 +79,6 @@ module.exports = {
Description: description,
},
},

[validatorLogicalId]: {
Type: 'AWS::ApiGateway::RequestValidator',
Properties: {
RestApiId: this.provider.getApiGatewayRestApiId(),
ValidateRequestBody: true,
ValidateRequestParameters: true,
Name: validatorName,
},
},
}
);
}
Expand All @@ -107,9 +99,11 @@ module.exports = {
contentType
);

const validatorLogicalId = this.provider.naming.getValidatorLogicalId(
this.provider.naming.getModelLogicalId(resourceName)
);
if (!validatorLogicalId) {
const requestValidator = this.createRequestValidator();
validatorLogicalId = requestValidator.validatorLogicalId;
validatorName = requestValidator.validatorName;
}

template.Properties.RequestValidatorId = { Ref: validatorLogicalId };
template.Properties.RequestModels = template.Properties.RequestModels || {};
Expand All @@ -124,23 +118,14 @@ module.exports = {
Schema: schema,
},
},
[validatorLogicalId]: {
Type: 'AWS::ApiGateway::RequestValidator',
Properties: {
RestApiId: this.provider.getApiGatewayRestApiId(),
ValidateRequestBody: true,
ValidateRequestParameters: true,
},
},
});
}
}
});
},

createProviderModel(schemaId, schemaConfig) {
createProviderModel(schemaId, schemaConfig, validatorLogicalId, validatorName) {
let modelName;
let validatorName;
let description;
let definition;

Expand All @@ -153,8 +138,6 @@ module.exports = {

const modelLogicalId = this.provider.naming.getModelLogicalId(schemaId);

const validatorLogicalId = this.provider.naming.getValidatorLogicalId(modelLogicalId);

if (schemaConfig.name) {
modelName = schemaConfig.name;
validatorName = `${modelName}Validator`;
Expand All @@ -173,14 +156,6 @@ module.exports = {
ContentType: 'application/json',
},
},
[validatorLogicalId]: {
Type: 'AWS::ApiGateway::RequestValidator',
Properties: {
RestApiId: { Ref: this.apiGatewayRestApiLogicalId },
ValidateRequestBody: true,
ValidateRequestParameters: true,
},
},
});

if (modelName) {
Expand All @@ -197,9 +172,26 @@ module.exports = {
modelLogicalId
].Properties.Description = description;
}
return modelLogicalId;
},

createRequestValidator() {
const validatorLogicalId = this.provider.naming.getValidatorLogicalId();
const validatorName = 'Validate request body and querystring parameters';
this.serverless.service.provider.compiledCloudFormationTemplate.Resources[
validatorLogicalId
] = {
Type: 'AWS::ApiGateway::RequestValidator',
Properties: {
RestApiId: this.provider.getApiGatewayRestApiId(),
ValidateRequestBody: true,
ValidateRequestParameters: true,
Name: validatorName,
},
};
return {
modelLogicalId,
validatorLogicalId,
validatorName,
};
},
};
5 changes: 2 additions & 3 deletions test/unit/lib/plugins/aws/lib/naming.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -416,9 +416,8 @@ describe('#naming()', () => {

describe('#getValidatorLogicalId()', () => {
it('', () => {
expect(sdk.naming.getValidatorLogicalId('ApiGatewayMethodResourceId')).to.equal(
'ApiGatewayMethodResourceIdValidator'
);
serverless.service.service = 'my-Service';
expect(sdk.naming.getValidatorLogicalId()).to.equal('ApiGatewayMyServiceRequestValidator');
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ describe('#compileRequestValidators()', () => {
**/
it('should reference model from provider:apiGateway:requestSchemas', () => {
const modelLogicalId = naming.getModelLogicalId('test-model');
const validatorLogicalId = naming.getValidatorLogicalId(modelLogicalId);
const validatorLogicalId = naming.getValidatorLogicalId();
const methodLogicalId = naming.getMethodLogicalId('TestDashmodelDashfull', 'get');
const methodResource = cfResources[methodLogicalId];

Expand All @@ -116,9 +116,7 @@ describe('#compileRequestValidators()', () => {
'get',
'application/json'
);
const validatorLogicalId = naming.getValidatorLogicalId(
naming.getModelLogicalId('TestDashdirectDashsimple')
);
const validatorLogicalId = naming.getValidatorLogicalId();
const methodLogicalId = naming.getMethodLogicalId('TestDashdirectDashsimple', 'get');
const methodResource = cfResources[methodLogicalId];

Expand Down Expand Up @@ -168,9 +166,7 @@ describe('#compileRequestValidators()', () => {
'get',
'application/json'
);
const validatorLogicalId = naming.getValidatorLogicalId(
naming.getModelLogicalId('TestDashdirectDashfull')
);
const validatorLogicalId = naming.getValidatorLogicalId();
const methodLogicalId = naming.getMethodLogicalId('TestDashdirectDashfull', 'get');
const methodResource = cfResources[methodLogicalId];

Expand Down Expand Up @@ -225,9 +221,7 @@ describe('#compileRequestValidators()', () => {
'get',
'text/plain'
);
const validatorLogicalId = naming.getValidatorLogicalId(
naming.getModelLogicalId('TestDashmultiple')
);
const validatorLogicalId = naming.getValidatorLogicalId();
const methodLogicalId = naming.getMethodLogicalId('TestDashmultiple', 'get');
const methodResource = cfResources[methodLogicalId];

Expand Down Expand Up @@ -295,9 +289,7 @@ describe('#compileRequestValidators()', () => {
'get',
'application/json'
);
const validatorLogicalId = naming.getValidatorLogicalId(
naming.getModelLogicalId('TestDashdeprecatedDashsimple')
);
const validatorLogicalId = naming.getValidatorLogicalId();
const methodLogicalId = naming.getMethodLogicalId('TestDashdeprecatedDashsimple', 'get');
const methodResource = cfResources[methodLogicalId];

Expand Down Expand Up @@ -350,9 +342,7 @@ describe('#compileRequestValidators()', () => {
'get',
'text/plain'
);
const validatorLogicalId = naming.getValidatorLogicalId(
naming.getModelLogicalId('TestDashdeprecatedDashmultiple')
);
const validatorLogicalId = naming.getValidatorLogicalId();
const methodLogicalId = naming.getMethodLogicalId('TestDashdeprecatedDashmultiple', 'get');
const methodResource = cfResources[methodLogicalId];

Expand Down

0 comments on commit 154351f

Please sign in to comment.