Skip to content

Commit

Permalink
Add cache-control for assets served via registerStaticDir (#102756)
Browse files Browse the repository at this point in the history
* Add cache-control for assets served via `registerStaticDir`

* fix case

* add test for 'dynamic' file content
  • Loading branch information
pgayvallet authored Jun 22, 2021
1 parent df8637a commit fc55c30
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 5 deletions.
127 changes: 123 additions & 4 deletions src/core/server/http/http_server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
*/

import { Server } from 'http';
import { readFileSync } from 'fs';
import { rmdir, mkdtemp, readFile, writeFile } from 'fs/promises';
import supertest from 'supertest';
import { omit } from 'lodash';
import { join } from 'path';

import { ByteSizeValue, schema } from '@kbn/config-schema';
import { HttpConfig } from './http_config';
Expand Down Expand Up @@ -47,9 +48,9 @@ const enhanceWithContext = (fn: (...args: any[]) => any) => fn.bind(null, {});
let certificate: string;
let key: string;

beforeAll(() => {
certificate = readFileSync(KBN_CERT_PATH, 'utf8');
key = readFileSync(KBN_KEY_PATH, 'utf8');
beforeAll(async () => {
certificate = await readFile(KBN_CERT_PATH, 'utf8');
key = await readFile(KBN_KEY_PATH, 'utf8');
});

beforeEach(() => {
Expand Down Expand Up @@ -1409,13 +1410,131 @@ describe('setup contract', () => {
});

describe('#registerStaticDir', () => {
const assetFolder = join(__dirname, 'integration_tests', 'fixtures', 'static');
let tempDir: string;

beforeAll(async () => {
tempDir = await mkdtemp('cache-test');
});

afterAll(async () => {
if (tempDir) {
await rmdir(tempDir, { recursive: true });
}
});

test('does not throw if called after stop', async () => {
const { registerStaticDir } = await server.setup(config);
await server.stop();
expect(() => {
registerStaticDir('/path1/{path*}', '/path/to/resource');
}).not.toThrow();
});

test('returns correct headers for static assets', async () => {
const { registerStaticDir, server: innerServer } = await server.setup(config);

registerStaticDir('/static/{path*}', assetFolder);

await server.start();
const response = await supertest(innerServer.listener)
.get('/static/some_json.json')
.expect(200);

expect(response.get('cache-control')).toEqual('must-revalidate');
expect(response.get('etag')).not.toBeUndefined();
});

test('returns compressed version if present', async () => {
const { registerStaticDir, server: innerServer } = await server.setup(config);

registerStaticDir('/static/{path*}', assetFolder);

await server.start();
const response = await supertest(innerServer.listener)
.get('/static/compression_available.json')
.set('accept-encoding', 'gzip')
.expect(200);

expect(response.get('cache-control')).toEqual('must-revalidate');
expect(response.get('etag')).not.toBeUndefined();
expect(response.get('content-encoding')).toEqual('gzip');
});

test('returns uncompressed version if compressed asset is not available', async () => {
const { registerStaticDir, server: innerServer } = await server.setup(config);

registerStaticDir('/static/{path*}', assetFolder);

await server.start();
const response = await supertest(innerServer.listener)
.get('/static/some_json.json')
.set('accept-encoding', 'gzip')
.expect(200);

expect(response.get('cache-control')).toEqual('must-revalidate');
expect(response.get('etag')).not.toBeUndefined();
expect(response.get('content-encoding')).toBeUndefined();
});

test('returns a 304 if etag value matches', async () => {
const { registerStaticDir, server: innerServer } = await server.setup(config);

registerStaticDir('/static/{path*}', assetFolder);

await server.start();
const response = await supertest(innerServer.listener)
.get('/static/some_json.json')
.expect(200);

const etag = response.get('etag');
expect(etag).not.toBeUndefined();

await supertest(innerServer.listener)
.get('/static/some_json.json')
.set('If-None-Match', etag)
.expect(304);
});

test('serves content if etag values does not match', async () => {
const { registerStaticDir, server: innerServer } = await server.setup(config);

registerStaticDir('/static/{path*}', assetFolder);

await server.start();

await supertest(innerServer.listener)
.get('/static/some_json.json')
.set('If-None-Match', `"definitely not a valid etag"`)
.expect(200);
});

test('dynamically updates depending on the content of the file', async () => {
const tempFile = join(tempDir, 'some_file.json');

const { registerStaticDir, server: innerServer } = await server.setup(config);
registerStaticDir('/static/{path*}', tempDir);

await server.start();

await supertest(innerServer.listener).get('/static/some_file.json').expect(404);

await writeFile(tempFile, `{ "over": 9000 }`);

let response = await supertest(innerServer.listener)
.get('/static/some_file.json')
.expect(200);

const etag1 = response.get('etag');

await writeFile(tempFile, `{ "over": 42 }`);

response = await supertest(innerServer.listener).get('/static/some_file.json').expect(200);

const etag2 = response.get('etag');

expect(etag1).not.toEqual(etag2);
});
});

describe('#registerOnPreRouting', () => {
Expand Down
8 changes: 7 additions & 1 deletion src/core/server/http/http_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,13 @@ export class HttpServer {
lookupCompressed: true,
},
},
options: { auth: false },
options: {
auth: false,
cache: {
privacy: 'public',
otherwise: 'must-revalidate',
},
},
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"hello": "dolly"
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"foo": "bar"
}

0 comments on commit fc55c30

Please sign in to comment.