Skip to content

Commit 162d771

Browse files
author
diana.ionita
committed
Merge branch 'release/1.2.1'
2 parents e505d19 + e2d3b9b commit 162d771

6 files changed

+165
-71
lines changed

README.md

+59-13
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ You can configure how to handle unauthorized requests to invalidate a cache key
1818
* `IgnoreWithWarning` - ignores the request to invalidate and adds a `warning` header in the response.
1919
* `Fail` - fails the request to invalidate the cache key with a 403 response status code.
2020

21-
## Currently not supported:
22-
* lambda functions with many HTTP events.
21+
## Examples
2322

24-
## Example
23+
### Minimal setup
2524

2625
```yml
2726
plugins:
@@ -31,24 +30,71 @@ custom:
3130
# Enable or disable caching globally
3231
apiGatewayCaching:
3332
enabled: true
34-
clusterSize: '0.5' # defaults to '0.5'
35-
ttlInSeconds: 300 # defaults to the maximum allowed: 3600
36-
perKeyInvalidation:
37-
requireAuthorization: true # default is true
38-
handleUnauthorizedRequests: IgnoreWithWarning # default is "IgnoreWithWarning"
3933

4034
functions:
41-
# Responses are not cached
35+
# Responses are cached
4236
list-all-cats:
4337
handler: rest_api/cats/get/handler.handle
44-
role: listCatsRole
4538
events:
4639
- http:
4740
path: /cats
4841
method: get
4942
caching:
50-
enabled: false # default is false
43+
enabled: true
5144

45+
# Responses are *not* cached
46+
update-cat:
47+
handler: rest_api/cat/post/handler.handle
48+
events:
49+
- http:
50+
path: /cat
51+
method: post
52+
53+
# Responses are cached based on the 'pawId' path parameter and the 'Accept-Language' header
54+
get-cat-by-paw-id:
55+
handler: rest_api/cat/get/handler.handle
56+
events:
57+
- http:
58+
path: /cats/{pawId}
59+
method: get
60+
caching:
61+
enabled: true
62+
cacheKeyParameters:
63+
- name: request.path.pawId
64+
- name: request.header.Accept-Language
65+
```
66+
67+
### Configuring the cache cluster size and cache time to live
68+
Cache time to live and invalidation settings are applied to all functions, unless specifically overridden.
69+
70+
```yml
71+
plugins:
72+
- serverless-api-gateway-caching
73+
74+
custom:
75+
# Enable or disable caching globally
76+
apiGatewayCaching:
77+
enabled: true
78+
clusterSize: '0.5' # defaults to '0.5'
79+
ttlInSeconds: 300 # defaults to the maximum allowed: 3600
80+
perKeyInvalidation:
81+
requireAuthorization: true # default is true
82+
handleUnauthorizedRequests: Ignore # default is "IgnoreWithWarning"
83+
84+
```
85+
86+
### Configuring per-function cache time to live, cache invalidation strategy and cache key parameters
87+
88+
```yml
89+
plugins:
90+
- serverless-api-gateway-caching
91+
92+
custom:
93+
# Enable or disable caching globally
94+
apiGatewayCaching:
95+
enabled: true
96+
97+
functions:
5298
# Responses are cached based on the 'pawId' path parameter and the 'Accept-Language' header
5399
get-cat-by-paw-id:
54100
handler: rest_api/cat/get/handler.handle
@@ -60,8 +106,8 @@ functions:
60106
enabled: true
61107
ttlInSeconds: 3600
62108
perKeyInvalidation:
63-
requireAuthorization: true
64-
handleUnauthorizedRequests: Ignore
109+
requireAuthorization: true # default is true
110+
handleUnauthorizedRequests: Fail # default is "IgnoreWithWarning"
65111
cacheKeyParameters:
66112
- name: request.path.pawId
67113
- name: request.header.Accept-Language

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "serverless-api-gateway-caching",
3-
"version": "1.2.0",
3+
"version": "1.2.1",
44
"description": "A plugin for the serverless framework which helps with configuring caching for API Gateway endpoints.",
55
"main": "src/apiGatewayCachingPlugin.js",
66
"scripts": {

src/pathParametersCache.js

+18-17
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,36 @@ const getResourcesByName = (name, serverless) => {
1010
}
1111

1212
const getApiGatewayMethodNameFor = (path, httpMethod) => {
13-
const pathElements = split(path,'/');
13+
const pathElements = split(path, '/');
1414
pathElements.push(httpMethod.toLowerCase());
1515
let gatewayResourceName = pathElements
16-
.map (element => {
17-
element = element.toLowerCase();
18-
if(element.startsWith('{')) {
19-
element = element.substring(element.indexOf('{') + 1,element.indexOf('}')) + "Var";
20-
}
21-
//capitalize first letter
22-
return element.charAt(0).toUpperCase() + element.slice(1);
23-
}).reduce((a, b) => a + b);
16+
.map(element => {
17+
element = element.toLowerCase();
18+
element = element.replace('+', '');
19+
if (element.startsWith('{')) {
20+
element = element.substring(element.indexOf('{') + 1, element.indexOf('}')) + "Var";
21+
}
22+
//capitalize first letter
23+
return element.charAt(0).toUpperCase() + element.slice(1);
24+
}).reduce((a, b) => a + b);
2425

25-
gatewayResourceName = "ApiGatewayMethod" + gatewayResourceName;
26-
return gatewayResourceName;
26+
gatewayResourceName = "ApiGatewayMethod" + gatewayResourceName;
27+
return gatewayResourceName;
2728
}
2829

2930
const addPathParametersCacheConfig = (settings, serverless) => {
3031
for (let endpointSettings of settings.endpointSettings) {
3132
if (!endpointSettings.cacheKeyParameters) {
3233
continue;
33-
}
34+
}
3435
const resourceName = getApiGatewayMethodNameFor(endpointSettings.path, endpointSettings.method);
35-
const method = getResourcesByName(resourceName,serverless);
36-
if (!method) {
36+
const method = getResourcesByName(resourceName, serverless);
37+
if (!method) {
3738
serverless.cli.log(`[serverless-api-gateway-caching] The method ${resourceName} couldn't be found in the
3839
compiled CloudFormation template. Caching settings will not be updated for this endpoint.`);
3940
const index = settings.endpointSettings.indexOf(endpointSettings);
40-
if(index != -1) {
41-
settings.endpointSettings.splice(index,1);
41+
if (index != -1) {
42+
settings.endpointSettings.splice(index, 1);
4243
}
4344
return;
4445
}
@@ -59,7 +60,7 @@ const addPathParametersCacheConfig = (settings, serverless) => {
5960
}
6061
}
6162

62-
module.exports = {
63+
module.exports = {
6364
addPathParametersCacheConfig: addPathParametersCacheConfig,
6465
getApiGatewayMethodNameFor: getApiGatewayMethodNameFor
6566
}

test/configuring-path-parameters.js

+80-33
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,19 @@ const pathParams = require(`${APP_ROOT}/src/pathParametersCache`);
55
const expect = require('chai').expect;
66

77
describe('Configuring path parameter caching', () => {
8-
let serverless, cacheSettings;
8+
let serverless;
99
let serviceName = 'cat-api', stage = 'dev';
1010

1111
describe('when there are no endpoints', () => {
1212
before(() => {
1313
serverless = given.a_serverless_instance(serviceName)
1414
.withApiGatewayCachingConfig(true, '0.5', 45)
1515
.forStage(stage);
16-
cacheSettings = new ApiGatewayCachingSettings(serverless);
1716
});
1817

1918
it('should do nothing to the serverless instance', () => {
2019
let stringified = JSON.stringify(serverless);
21-
when_configuring_path_parameters(cacheSettings, serverless);
20+
when_configuring_path_parameters(serverless);
2221
let stringifiedAfter = JSON.stringify(serverless);
2322
expect(stringified).to.equal(stringifiedAfter);
2423
});
@@ -32,12 +31,11 @@ describe('Configuring path parameter caching', () => {
3231
.withApiGatewayCachingConfig(true, '0.5', 45)
3332
.forStage(stage)
3433
.withFunction(endpoint);
35-
cacheSettings = new ApiGatewayCachingSettings(serverless);
3634
});
3735

3836
it('should do nothing to the serverless instance', () => {
3937
let stringified = JSON.stringify(serverless);
40-
when_configuring_path_parameters(cacheSettings, serverless);
38+
when_configuring_path_parameters(serverless);
4139
let stringifiedAfter = JSON.stringify(serverless);
4240
expect(stringified).to.equal(stringifiedAfter);
4341
});
@@ -61,9 +59,8 @@ describe('Configuring path parameter caching', () => {
6159
.forStage(stage)
6260
.withFunction(functionWithCaching)
6361
.withFunction(functionWithoutCaching);
64-
cacheSettings = new ApiGatewayCachingSettings(serverless);
6562

66-
when_configuring_path_parameters(cacheSettings, serverless);
63+
when_configuring_path_parameters(serverless);
6764
});
6865

6966
describe('on the method corresponding with the endpoint with cache key parameters', () => {
@@ -156,8 +153,7 @@ describe('Configuring path parameter caching', () => {
156153
method = serverless.getMethodResourceForFunction(functionWithCachingName);
157154
method.Properties.RequestParameters[`method.${cacheKeyParameters[0].name}`] = isRequired;
158155

159-
cacheSettings = new ApiGatewayCachingSettings(serverless);
160-
when_configuring_path_parameters(cacheSettings, serverless)
156+
when_configuring_path_parameters(serverless)
161157
});
162158

163159
it('should keep configuration', () => {
@@ -191,9 +187,7 @@ describe('Configuring path parameter caching', () => {
191187
.withFunction(firstFunctionWithCaching)
192188
.withFunction(secondFunctionWithCaching);
193189

194-
cacheSettings = new ApiGatewayCachingSettings(serverless);
195-
196-
when_configuring_path_parameters(cacheSettings, serverless);
190+
when_configuring_path_parameters(serverless);
197191
});
198192

199193
describe('on the method corresponding with the first endpoint with cache key parameters', () => {
@@ -267,26 +261,25 @@ describe('Configuring path parameter caching', () => {
267261
});
268262
});
269263
});
264+
270265
describe('when there are two endpoints with a cache key parameter on the same function', () => {
271-
let method, functionName, firstEndpointCacheKeyParameters, secondEndpointCacheKeyParameters;
272-
before(() => {
273-
functionName = 'catpaw';
274-
275-
firstEndpointCacheKeyParameters = [{ name: 'request.path.pawId' }];
276-
secondEndpointCacheKeyParameters = [{ name: 'request.path.pawId' }];
266+
let method, functionName, firstEndpointCacheKeyParameters, secondEndpointCacheKeyParameters;
267+
before(() => {
268+
functionName = 'catpaw';
277269

278-
let firstFunctionWithCaching = given.a_serverless_function(functionName)
279-
.withHttpEndpoint('get', '/cat/paw/{pawId}', { enabled: true, cacheKeyParameters: firstEndpointCacheKeyParameters })
280-
.withHttpEndpoint('delete', '/cat/paw/{pawId}', { enabled: true, cacheKeyParameters: secondEndpointCacheKeyParameters });
281-
serverless = given.a_serverless_instance(serviceName)
282-
.withApiGatewayCachingConfig(true, '0.5', 45)
283-
.forStage(stage)
284-
.withFunction(firstFunctionWithCaching)
285-
286-
cacheSettings = new ApiGatewayCachingSettings(serverless);
270+
firstEndpointCacheKeyParameters = [{ name: 'request.path.pawId' }];
271+
secondEndpointCacheKeyParameters = [{ name: 'request.path.pawId' }];
287272

288-
when_configuring_path_parameters(cacheSettings, serverless);
289-
});
273+
let firstFunctionWithCaching = given.a_serverless_function(functionName)
274+
.withHttpEndpoint('get', '/cat/paw/{pawId}', { enabled: true, cacheKeyParameters: firstEndpointCacheKeyParameters })
275+
.withHttpEndpoint('delete', '/cat/paw/{pawId}', { enabled: true, cacheKeyParameters: secondEndpointCacheKeyParameters });
276+
serverless = given.a_serverless_instance(serviceName)
277+
.withApiGatewayCachingConfig(true, '0.5', 45)
278+
.forStage(stage)
279+
.withFunction(firstFunctionWithCaching)
280+
281+
when_configuring_path_parameters(serverless);
282+
});
290283

291284
describe('on the method corresponding with the first endpoint with cache key parameters', () => {
292285
before(() => {
@@ -324,7 +317,7 @@ describe('Configuring path parameter caching', () => {
324317
});
325318

326319
describe('on the method corresponding with the second endpoint with cache key parameters', () => {
327-
before(() => {
320+
before(() => {
328321
method = serverless.getMethodResourceForMethodName("ApiGatewayMethodCatPawPawidVarDelete");
329322
});
330323

@@ -349,7 +342,60 @@ describe('Configuring path parameter caching', () => {
349342
it('should set integration cache key parameters', () => {
350343
for (let parameter of secondEndpointCacheKeyParameters) {
351344
expect(method.Properties.Integration.CacheKeyParameters)
352-
.to.include(`method.${parameter.name}`);
345+
.to.include(`method.${parameter.name}`);
346+
}
347+
});
348+
349+
it('should set a cache namespace', () => {
350+
expect(method.Properties.Integration.CacheNamespace).to.exist;
351+
});
352+
});
353+
});
354+
355+
describe('when an http event path contains the \'+\' special character', () => {
356+
let cacheKeyParameters, functionWithCachingName;
357+
before(() => {
358+
functionWithCachingName = 'get-cat-by-paw-id';
359+
cacheKeyParameters = [{ name: 'request.path.pawId' }, { name: 'request.header.Accept-Language' }];
360+
361+
let functionWithCaching = given.a_serverless_function(functionWithCachingName)
362+
.withHttpEndpoint('get', '/cat/{pawId+}', { enabled: true, cacheKeyParameters });
363+
364+
serverless = given.a_serverless_instance(serviceName)
365+
.withApiGatewayCachingConfig(true, '0.5', 45)
366+
.forStage(stage)
367+
.withFunction(functionWithCaching);
368+
369+
when_configuring_path_parameters(serverless)
370+
});
371+
372+
describe('on the corresponding method', () => {
373+
before(() => {
374+
method = serverless.getMethodResourceForFunction(functionWithCachingName);
375+
});
376+
377+
it('should configure cache key parameters as request parameters', () => {
378+
for (let parameter of cacheKeyParameters) {
379+
expect(method.Properties.RequestParameters)
380+
.to.deep.include({
381+
[`method.${parameter.name}`]: {}
382+
});
383+
}
384+
});
385+
386+
it('should set integration request parameters', () => {
387+
for (let parameter of cacheKeyParameters) {
388+
expect(method.Properties.Integration.RequestParameters)
389+
.to.deep.include({
390+
[`integration.${parameter.name}`]: `method.${parameter.name}`
391+
});
392+
}
393+
});
394+
395+
it('should set integration cache key parameters', () => {
396+
for (let parameter of cacheKeyParameters) {
397+
expect(method.Properties.Integration.CacheKeyParameters)
398+
.to.include(`method.${parameter.name}`);
353399
}
354400
});
355401

@@ -360,6 +406,7 @@ describe('Configuring path parameter caching', () => {
360406
});
361407
});
362408

363-
const when_configuring_path_parameters = (settings, serverless) => {
364-
return pathParams.addPathParametersCacheConfig(settings, serverless);
409+
const when_configuring_path_parameters = (serverless) => {
410+
let cacheSettings = new ApiGatewayCachingSettings(serverless);
411+
return pathParams.addPathParametersCacheConfig(cacheSettings, serverless);
365412
}

0 commit comments

Comments
 (0)