Skip to content

Commit

Permalink
feat: allow to disable the cache
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelKreil committed Feb 3, 2024
1 parent a783156 commit f1dd902
Show file tree
Hide file tree
Showing 10 changed files with 59 additions and 59 deletions.
2 changes: 2 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ describe('index.ts', () => {
baseUrl: undefined,
compress: false,
host: '0.0.0.0',
noCache: false,
port: 8080,
static: undefined,
tms: false,
};

Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ program
.option('-b, --base-url <url>', 'Base URL for the server (default: "http://localhost:<port>/")')
.option('-c, --compress', 'Reduces traffic by recompressing data, but responses take longer. Perfect if behind CDN.')
.option('-h, --host <hostnameip>', 'Hostname or IP to bind the server to', '0.0.0.0')
.option('-n, --no-cache', 'disable cache and serve static files directly from disc')
.option('-o, --open', 'Open map in web browser')
.option('-p, --port <port>', 'Port to bind the server to (default: 8080)')
.option('-s, --static <folder>', 'Path to a folder with static files')
Expand All @@ -29,6 +30,7 @@ program
baseUrl: cmdOptions.baseUrl as string | undefined,
compress: Boolean(cmdOptions.compress),
host: String(cmdOptions.host ?? '0.0.0.0'),
noCache: Boolean(cmdOptions.noCache),
port: Number(cmdOptions.port ?? 8080),
static: cmdOptions.static as string | undefined,
tms: Boolean(cmdOptions.tms),
Expand Down
2 changes: 1 addition & 1 deletion src/lib/layer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('Layer class', () => {

const tileResponse = await tileFunc(8, 55, 67);
expect(tileResponse).toBeDefined();
expect(tileResponse?.buffer.length).toBe(3548);
expect(tileResponse?.content.length).toBe(3548);
expect(tileResponse?.mime).toBe('application/x-protobuf');
expect(tileResponse?.compression).toBe('br');
});
Expand Down
10 changes: 3 additions & 7 deletions src/lib/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,9 @@ export class Layer {
const compression = this.#compression;

return async (z: number, x: number, y: number): Promise<ContentResponse | null> => {
const buffer = await container.getTile(z, x, y);
if (!buffer) return null;
return {
buffer,
mime: mime,
compression: compression,
};
const content = await container.getTile(z, x, y);
if (!content) return null;
return { content, mime, compression };
};
}

Expand Down
8 changes: 4 additions & 4 deletions src/lib/response.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('Response Tests', () => {

describe('respond with content', () => {
it('should set correct headers and respond with content', async () => {
const content = { buffer: 'test', mime: 'text/plain' };
const content = { content: Buffer.from('test'), mime: 'text/plain' };
const config = { acceptGzip: true, acceptBr: false, optimalCompression: false };

await respondWithContent(mockRes, content, config);
Expand All @@ -37,9 +37,9 @@ describe('Response Tests', () => {
expect(mockRes.statusCode).toBe(200);
expect(mockRes.end).toHaveBeenCalledWith(Buffer.from('test'));
});

it('should set correct mime if missing', async () => {
const content = { buffer: 'test' };
const content = { content: Buffer.from('test') };
const config = { acceptGzip: true, acceptBr: false, optimalCompression: false };

await respondWithContent(mockRes, content, config);
Expand Down Expand Up @@ -96,7 +96,7 @@ describe('Response Tests', () => {
// eslint-disable-next-line @typescript-eslint/no-loop-func
it(`${buffer} -> ${accept} (${optimal ? 'optimal' : 'fast'})`, async () => {
const content: ContentResponse = {
buffer: buffers[buffer],
content: buffers[buffer],
mime: 'text/plain',
compression: buffer,
};
Expand Down
14 changes: 10 additions & 4 deletions src/lib/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@ import type { Compression } from '@versatiles/container';
import type { ServerResponse } from 'http';
import { brotli, gzip, unbrotli, ungzip } from './compressors.js';
import type { ResponseConfig, ContentResponse } from './types.js';
import { readFile } from 'node:fs/promises';

export async function respondWithContent(res: ServerResponse, content: ContentResponse, config: ResponseConfig): Promise<void> {
const mime: string = content.mime ?? 'application/octet-stream';
let compression: Compression = content.compression ?? 'raw';
export async function respondWithContent(res: ServerResponse, response: ContentResponse, config: ResponseConfig): Promise<void> {
const mime: string = response.mime ?? 'application/octet-stream';
let compression: Compression = response.compression ?? 'raw';

const { acceptGzip, acceptBr, optimalCompression } = config;

let data: Buffer = (typeof content.buffer === 'string') ? Buffer.from(content.buffer) : content.buffer;
let data: Buffer;
if (typeof response.content === 'string') {
data = await readFile(response.content);
} else {
data = response.content;
}

switch (compression) {
case 'br':
Expand Down
14 changes: 6 additions & 8 deletions src/lib/server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { createServer } from 'node:http';
import { Layer } from './layer.js';
import { readFileSync } from 'node:fs';
import { resolve as resolvePath } from 'node:path';
import { respondWithContent, respondWithError } from './response.js';
import { StaticContent } from './static_content.js';
Expand Down Expand Up @@ -119,20 +118,19 @@ export class Server {
}

async #buildStaticContent(): Promise<StaticContent> {
const staticContent = new StaticContent();
const staticContent = new StaticContent(this.#options.noCache ?? false);

const html = readFileSync(resolvePath(DIRNAME, 'static/index.html'));
staticContent.add('/index.html', html, 'text/html; charset=utf-8');
staticContent.addFile('/index.html', resolvePath(DIRNAME, 'static/index.html'), 'text/html; charset=utf-8');

staticContent.add(
staticContent.addFile(
'/tiles/style.json',
await this.#layer.getStyle(this.#options),
Buffer.from(await this.#layer.getStyle(this.#options)),
'application/json; charset=utf-8',
);

staticContent.add(
staticContent.addFile(
'/tiles/tile.json',
await this.#layer.getMetadata() ?? {},
Buffer.from(await this.#layer.getMetadata() ?? ''),
'application/json; charset=utf-8',
);

Expand Down
24 changes: 12 additions & 12 deletions src/lib/static_content.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe('StaticContent', () => {
let staticContent: StaticContent;

beforeEach(() => {
staticContent = new StaticContent();
staticContent = new StaticContent(false);
});

describe('constructor', () => {
Expand All @@ -18,27 +18,27 @@ describe('StaticContent', () => {
describe('add method', () => {
it('should add text content', () => {
const path = '/text';
const content = 'Hello World';
const content = Buffer.from('Hello World');
const mime = 'text/plain';
staticContent.add(path, content, mime);
expect(staticContent.get(path)).toEqual({ buffer: Buffer.from(content), mime, compression: 'raw' });
staticContent.addFile(path, content, mime);
expect(staticContent.get(path)).toEqual({ content, mime, compression: 'raw' });
});

it('should serve "/index.html" under "/"', () => {
const path = '/index.html';
const content = 'Hello World';
const content = Buffer.from('Hello World');
const mime = 'text/plain';
staticContent.add(path, content, mime);
expect(staticContent.get('/')).toEqual({ buffer: Buffer.from(content), mime, compression: 'raw' });
staticContent.addFile(path, content, mime);
expect(staticContent.get('/')).toEqual({ content, mime, compression: 'raw' });
});

it('should serve "/data/index.html" under "/data/" and "/data"', () => {
const path = '/data/index.html';
const content = 'Hello World';
const content = Buffer.from('Hello World');
const mime = 'text/plain';
staticContent.add(path, content, mime);
expect(staticContent.get('/data')).toEqual({ buffer: Buffer.from(content), mime, compression: 'raw' });
expect(staticContent.get('/data/')).toEqual({ buffer: Buffer.from(content), mime, compression: 'raw' });
staticContent.addFile(path, content, mime);
expect(staticContent.get('/data')).toEqual({ content, mime, compression: 'raw' });
expect(staticContent.get('/data/')).toEqual({ content, mime, compression: 'raw' });
});
});

Expand Down Expand Up @@ -66,7 +66,7 @@ describe('StaticContent', () => {
files.forEach((file: string) => {
const expectedPath = url + file;
expect(staticContent.get(expectedPath)).toEqual({
buffer: readFileSync(resolve(dir, file)),
content: readFileSync(resolve(dir, file)),
mime: mimeTypes.get(file.replace(/.*\./, '')),
compression: 'raw',
});
Expand Down
27 changes: 11 additions & 16 deletions src/lib/static_content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ import { getMimeByFilename } from './mime_types.js';
export class StaticContent {
readonly #map: Map<string, ContentResponse>;

readonly #noCache: boolean;

/**
* Constructs a new instance of the StaticContent class.
*/
public constructor() {
public constructor(noCache: boolean) {
this.#noCache = noCache;
this.#map = new Map();
}

Expand Down Expand Up @@ -46,31 +49,23 @@ export class StaticContent {
/**
* Adds a new static response to the map.
* @param path - The path where the static response will be accessible.
* @param content - The content to serve, can be a Buffer, object, or string.
* @param content - The content to serve, can be content as a Buffer or path as a string.
* @param mime - The MIME type of the content.
* @param compression - The compression method used, if any.
* @throws Will throw an error if the path already exists in the map.
*/
// eslint-disable-next-line @typescript-eslint/max-params
public add(path: string, content: Buffer | object | string, mime: string, compression: Compression = 'raw'): void {
let buffer: Buffer;

if (Buffer.isBuffer(content)) {
buffer = content;
} else if (typeof content === 'string') {
buffer = Buffer.from(content);
} else {
buffer = Buffer.from(JSON.stringify(content));
}
public addFile(path: string, content: Buffer | string, mime: string, compression: Compression = 'raw'): void {
if ((typeof content === 'string') && !this.#noCache) content = readFileSync(content);

this.#map.set(path, { buffer, mime, compression });
this.#map.set(path, { content, mime, compression });

if (path.endsWith('/index.html')) {
path = path.replace(/index\.html$/, '');
this.#map.set(path, { buffer, mime, compression });
this.#map.set(path, { content, mime, compression });
if (path.length > 2) {
path = path.replace(/\/$/, '');
this.#map.set(path, { buffer, mime, compression });
this.#map.set(path, { content, mime, compression });
}
}
}
Expand Down Expand Up @@ -106,7 +101,7 @@ export class StaticContent {
subUrl = subUrl.replace(/\.[^.]+$/, '');
}

this.add(subUrl, readFileSync(subDir), getMimeByFilename(name, true), compression);
this.addFile(subUrl, subDir, getMimeByFilename(name, true), compression);
}
});
}
Expand Down
15 changes: 8 additions & 7 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Compression, Format } from '@versatiles/container';

export interface ContentResponse {
buffer: Buffer | string;
content: Buffer | string;
mime?: string;
compression?: Compression;
}
Expand All @@ -13,15 +13,16 @@ export interface ResponseConfig {
}

export interface ServerOptions {
compress?: boolean;
baseUrl?: string;
baseUrl?: string; // Base URL for the server (default: "http://localhost:<port>/")
compress?: boolean; // Reduces traffic by recompressing data, but responses take longer. Perfect if behind CDN.
glyphsUrl?: string;
host?: string; // Hostname or IP to bind the server to', '0.0.0.0'
noCache?: boolean; // disable cache and serve static files directly from disc
port?: number; // Port to bind the server to (default: 8080)
spriteUrl?: string;
static?: string; // Path to a folder with static files
tilesUrl?: string;
host?: string;
port?: number;
static?: string;
tms?: boolean;
tms?: boolean; // Use TMS tile order (flip y axis)
}

export interface ContainerInfo {
Expand Down

0 comments on commit f1dd902

Please sign in to comment.