Skip to content
This repository has been archived by the owner on Feb 28, 2022. It is now read-only.

Commit

Permalink
feat(utils): add cache-utils for merging cache-control headers
Browse files Browse the repository at this point in the history
  • Loading branch information
trieloff committed Mar 11, 2020
1 parent bf2fa24 commit 3568d39
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 2 deletions.
11 changes: 10 additions & 1 deletion src/html/data-sections.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const {
} = require('ferrum');
const removePosition = require('unist-util-remove-position');
const dotprop = require('dot-prop');
const { merge } = require('../utils/cache-helper');

const pattern = /{{([^{}]+)}}/g;
/**
Expand Down Expand Up @@ -158,9 +159,17 @@ async function fillDataSections(context, { downloader, logger }) {

// remember that we are using this source so that we can compute the
// surrogate key later

setdefault(context.content, 'sources', []);
context.content.sources.push(node.url);

// pass the cache control header through
const res = setdefault(context, 'response', {});
const headers = setdefault(res, 'headers', {});

headers['Cache-Control'] = merge(
headers['Cache-Control'],
downloadeddata.headers.get('cache-control'),
);
} catch (e) {
logger.warn(`Unable to parse JSON for data embed ${node.url}: ${e.message}`);
return node;
Expand Down
52 changes: 52 additions & 0 deletions src/utils/cache-helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
function directives(expression = '') {
const retval = expression.split(',')
.map((s) => s.trim())
.filter((s) => !!s)
.map((s) => s.split('='))
.map(([
directive,
value]) => [directive, Number.isNaN(Number.parseInt(value, 10))
? true
: Number.parseInt(value, 10)])
.reduce((obj, [directive, value]) => {
obj[directive] = value;
return obj;
}, {});
return retval;
}

function format(dirs = {}) {
return Object.entries(dirs)
.map(([directive, value]) => ((value === true || value === 1) ? directive : `${directive}=${value}`))
.join(', ');
}

function merge(in1 = '', in2 = '') {
const dirs1 = typeof in1 === 'string' ? directives(in1) : in1;
const dirs2 = typeof in2 === 'string' ? directives(in2) : in2;

const keys = [...Object.keys(dirs1), ...Object.keys(dirs2)];

const mergeval = keys.reduce((merged, key) => {
merged[key] = Math.min(
dirs1[key] || Number.MAX_SAFE_INTEGER,
dirs2[key] || Number.MAX_SAFE_INTEGER,
);
return merged;
}, {});

return typeof in1 === 'string' ? format(mergeval) : mergeval;
}

module.exports = { directives, format, merge };
84 changes: 84 additions & 0 deletions test/testCacheHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
/* eslint-env mocha */
const assert = require('assert');
const { directives, format, merge } = require('../src/utils/cache-helper');

describe('Cache Helper Tests (surrogate)', () => {
it('directive parses directives', () => {
assert.deepStrictEqual(directives('max-age=300'), {
'max-age': 300,
});

assert.deepStrictEqual(directives('s-maxage=300, max-age=300'), {
's-maxage': 300,
'max-age': 300,
});

assert.deepStrictEqual(directives('s-maxage=300, max-age=300, public'), {
's-maxage': 300,
'max-age': 300,
public: true,
});

assert.deepStrictEqual(directives(''), {});

assert.deepStrictEqual(directives(), {});
});

it('format formats directives', () => {
assert.equal(format({}), '');
assert.equal(format(undefined), '');

assert.equal(format({
'max-age': 300,
public: true,
}), 'max-age=300, public');
});

it('merge merges two directives', () => {
assert.deepEqual(merge({}, {}), {});

assert.deepEqual(merge({
'max-age': 300,
}, {
's-maxage': 300,
}), {
's-maxage': 300,
'max-age': 300,
});

assert.deepEqual(merge({
'max-age': 300,
's-maxage': 600,
}, {
's-maxage': 300,
'max-age': 600,
}), {
's-maxage': 300,
'max-age': 300,
});

assert.deepEqual(merge({
public: true,
}, {
private: true,
}), {
public: true,
private: true,
});

assert.equal(merge('max-age=300, public', 'max-age=600'), 'max-age=300, public');

assert.equal(merge(), '');
});
});
11 changes: 10 additions & 1 deletion test/testDataEmbeds.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ describe('Integration Test with Data Embeds', () => {
.reply(() => [404]);

nock('https://adobeioruntime.net')
.defaultReplyHeaders({
'Cache-Control': 'max-age=3600',
})
.get(/.*/)
.reply(() => [status, data]);

Expand All @@ -125,7 +128,11 @@ describe('Integration Test with Data Embeds', () => {

const result = await pipe(
(mycontext) => {
mycontext.response = { status: 200, body: mycontext.content.document.body.innerHTML };
if (!mycontext.response) {
mycontext.response = {};
}
mycontext.response.status = 200;
mycontext.response.body = mycontext.content.document.body.innerHTML;
},
context,
action,
Expand Down Expand Up @@ -213,6 +220,8 @@ https://docs.google.com/spreadsheets/d/e/someotheruri/pubhtml

assert.equal(res1.response.headers['Surrogate-Key'], 'PbTcuh0tIarmUOZM');
assert.equal(res2.response.headers['Surrogate-Key'], 'IkqgcxcG5+q8/cOT');

assert.equal(res1.response.headers['Cache-Control'], 'max-age=3600');
});

it('html.pipe processes data embeds in main document', async () => testEmbeds(
Expand Down

0 comments on commit 3568d39

Please sign in to comment.