Skip to content

Commit

Permalink
Merge branch 'release/1.7.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
Diana Ionita committed Apr 8, 2021
2 parents 010310d + 058f950 commit 25e3417
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 37 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ custom:
enabled: true
functions:
# Cache responses for POST requests based on the whole request body
# Cache responses for POST requests based on a part of the request body
cats-graphql:
handler: graphql/handler.handle
events:
Expand Down
5 changes: 3 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "serverless-api-gateway-caching",
"version": "1.7.1",
"version": "1.7.2",
"description": "A plugin for the serverless framework which helps with configuring caching for API Gateway endpoints.",
"main": "src/apiGatewayCachingPlugin.js",
"scripts": {
Expand All @@ -19,8 +19,7 @@
"license": "ISC",
"dependencies": {
"lodash.get": "^4.4.2",
"lodash.isempty": "^4.4.0",
"lodash.split": "^4.4.0"
"lodash.isempty": "^4.4.0"
},
"bugs": {
"url": "https://github.com/DianaIonita/serverless-api-gateway-caching/issues"
Expand All @@ -34,6 +33,7 @@
"chance": "^1.0.16",
"mocha": "^8.1.3",
"mocha-junit-reporter": "^1.18.0",
"proxyquire": "^2.1.0"
"proxyquire": "^2.1.0",
"lodash.split": "^4.4.0"
}
}
23 changes: 23 additions & 0 deletions src/ApiGatewayCachingSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,27 @@ const isApiGatewayEndpoint = event => {
return event.http ? true : false;
}

const getApiGatewayResourceNameFor = (path, httpMethod) => {
const pathElements = path.split('/');
pathElements.push(httpMethod.toLowerCase());
let gatewayResourceName = pathElements
.map(element => {
element = element.toLowerCase();
element = element.replaceAll('+', '');
element = element.replaceAll('_', '');
element = element.replaceAll('.', '');
element = element.replaceAll('-', 'Dash');
if (element.startsWith('{')) {
element = element.substring(element.indexOf('{') + 1, element.indexOf('}')) + "Var";
}
//capitalize first letter
return element.charAt(0).toUpperCase() + element.slice(1);
}).reduce((a, b) => a + b);

gatewayResourceName = "ApiGatewayMethod" + gatewayResourceName;
return gatewayResourceName;
}

class PerKeyInvalidationSettings {
constructor(cachingSettings) {
let { perKeyInvalidation } = cachingSettings;
Expand Down Expand Up @@ -57,6 +78,8 @@ class ApiGatewayEndpointCachingSettings {
this.path = this.path.slice(0, -1);
}

this.gatewayResourceName = getApiGatewayResourceNameFor(this.path, this.method);

let { basePath } = globalSettings;
if (basePath) {
if (!basePath.startsWith('/')) {
Expand Down
3 changes: 3 additions & 0 deletions src/apiGatewayCachingPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class ApiGatewayCachingPlugin {
apiGatewayCaching: {
properties: {
enabled: { type: 'boolean' },
apiGatewayIsShared: { type: 'boolean' },
basePath: { type: 'string' },
restApiId: { type: 'string' },
clusterSize: { type: 'string' },
ttlInSeconds: { type: 'number' },
dataEncrypted: { type: 'boolean' },
Expand Down
33 changes: 4 additions & 29 deletions src/pathParametersCache.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const split = require('lodash.split');

const getResourcesByName = (name, serverless) => {
let resourceKeys = Object.keys(serverless.service.provider.compiledCloudFormationTemplate.Resources);
for (let resourceName of resourceKeys) {
Expand All @@ -9,36 +7,14 @@ const getResourcesByName = (name, serverless) => {
}
}

const getApiGatewayMethodNameFor = (path, httpMethod) => {
const pathElements = split(path, '/');
pathElements.push(httpMethod.toLowerCase());
let gatewayResourceName = pathElements
.map(element => {
element = element.toLowerCase();
element = element.replaceAll('+', '');
element = element.replaceAll('_', '');
element = element.replaceAll('.', '');
element = element.replaceAll('-', 'Dash');
if (element.startsWith('{')) {
element = element.substring(element.indexOf('{') + 1, element.indexOf('}')) + "Var";
}
//capitalize first letter
return element.charAt(0).toUpperCase() + element.slice(1);
}).reduce((a, b) => a + b);

gatewayResourceName = "ApiGatewayMethod" + gatewayResourceName;
return gatewayResourceName;
}

const addPathParametersCacheConfig = (settings, serverless) => {
for (let endpointSettings of settings.endpointSettings) {
if (!endpointSettings.cacheKeyParameters) {
continue;
}
const resourceName = getApiGatewayMethodNameFor(endpointSettings.path, endpointSettings.method);
const method = getResourcesByName(resourceName, serverless);
const method = getResourcesByName(endpointSettings.gatewayResourceName, serverless);
if (!method) {
serverless.cli.log(`[serverless-api-gateway-caching] The method ${resourceName} couldn't be found in the
serverless.cli.log(`[serverless-api-gateway-caching] The method ${endpointSettings.gatewayResourceName} couldn't be found in the
compiled CloudFormation template. Caching settings will not be updated for this endpoint.`);
continue;
}
Expand Down Expand Up @@ -74,11 +50,10 @@ const addPathParametersCacheConfig = (settings, serverless) => {
method.Properties.Integration.CacheKeyParameters.push(cacheKeyParameter.name)
}
}
method.Properties.Integration.CacheNamespace = `${resourceName}CacheNS`;
method.Properties.Integration.CacheNamespace = `${endpointSettings.gatewayResourceName}CacheNS`;
}
}

module.exports = {
addPathParametersCacheConfig: addPathParametersCacheConfig,
getApiGatewayMethodNameFor: getApiGatewayMethodNameFor
addPathParametersCacheConfig: addPathParametersCacheConfig
}
79 changes: 79 additions & 0 deletions test/determining-api-gateway-resource-name.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
const given = require('../test/steps/given');
const expect = require('chai').expect;
const ApiGatewayCachingSettings = require('../src/ApiGatewayCachingSettings');

describe('Determining API Gateway resource names', () => {
const serviceName = 'cat-api';
const functionName = 'get-cat-by-paw-id';

const scenarios = [
{
path: '/',
method: 'GET',
expectedGatewayResourceName: 'ApiGatewayMethodGet'
},
{
path: '/',
method: 'POST',
expectedGatewayResourceName: 'ApiGatewayMethodPost'
},
{
path: '/cat/{pawId}',
method: 'GET',
expectedGatewayResourceName: 'ApiGatewayMethodCatPawidVarGet'
},
{
path: '/{id}',
method: 'PATCH',
expectedGatewayResourceName: 'ApiGatewayMethodIdVarPatch'
}
];
for (const scenario of scenarios) {


describe('when a base path is not specified', () => {
before(() => {
const endpoint = given
.a_serverless_function(functionName)
.withHttpEndpoint(scenario.method, scenario.path, { enabled: true });

const serverless = given
.a_serverless_instance(serviceName)
.withApiGatewayCachingConfig({ enabled: true })
.withFunction(endpoint);

settings = new ApiGatewayCachingSettings(serverless);
});

it('determines the resource name based on endpoint path and method', () => {
expect(gatewayResourceNameOf(functionName, settings)).to.equal(scenario.expectedGatewayResourceName);
});
});

describe('when a base path is specified', () => {
before(() => {
const endpoint = given
.a_serverless_function(functionName)
.withHttpEndpoint(scenario.method, scenario.path, { enabled: true });

const serverless = given
.a_serverless_instance(serviceName)
.withApiGatewayCachingConfig({ enabled: true, basePath: '/animals' })
.withFunction(endpoint);

settings = new ApiGatewayCachingSettings(serverless);
});

it('is not included in the API Gateway resource name', () => {
expect(gatewayResourceNameOf(functionName, settings)).to.equal(scenario.expectedGatewayResourceName);
});
});
}
});

const gatewayResourceNameOf = (functionName, settings) => {
return settings
.endpointSettings
.find(x => x.functionName === functionName)
.gatewayResourceName;
}
2 changes: 1 addition & 1 deletion test/model/Serverless.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class Serverless {
const clone = object => JSON.parse(JSON.stringify(object));

const createMethodResourceNameFor = (path, method) => {
const pathElements = split(path, '/');
const pathElements = path.split('/');
pathElements.push(method.toLowerCase());
let gatewayResourceName = pathElements
.map(element => {
Expand Down

0 comments on commit 25e3417

Please sign in to comment.