add verbose logging, improve headers

This commit is contained in:
acalcutt 2025-01-02 22:08:12 -05:00
parent 71335872bc
commit 0d72d5796a
6 changed files with 207 additions and 43 deletions

View file

@ -17,11 +17,7 @@ import {
isValidHttpUrl, isValidHttpUrl,
fetchTileData, fetchTileData,
} from './utils.js'; } from './utils.js';
import { import { getPMtilesInfo, openPMtiles } from './pmtiles_adapter.js';
getPMtilesInfo,
getPMtilesTile,
openPMtiles,
} from './pmtiles_adapter.js';
import { gunzipP, gzipP } from './promises.js'; import { gunzipP, gzipP } from './promises.js';
import { openMbTilesWrapper } from './mbtiles_wrapper.js'; import { openMbTilesWrapper } from './mbtiles_wrapper.js';
@ -30,12 +26,28 @@ export const serve_data = {
* Initializes the serve_data module. * Initializes the serve_data module.
* @param {object} options Configuration options. * @param {object} options Configuration options.
* @param {object} repo Repository object. * @param {object} repo Repository object.
* @param {object} programOpts - An object containing the program options
* @returns {express.Application} The initialized Express application. * @returns {express.Application} The initialized Express application.
*/ */
init: function (options, repo) { init: function (options, repo, programOpts) {
const { verbose } = programOpts;
const app = express().disable('x-powered-by'); const app = express().disable('x-powered-by');
/**
* Handles requests for tile data, responding with the tile image.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @param {string} req.params.id - ID of the tile.
* @param {string} req.params.z - Z coordinate of the tile.
* @param {string} req.params.x - X coordinate of the tile.
* @param {string} req.params.y - Y coordinate of the tile.
* @param {string} req.params.format - Format of the tile.
* @returns {Promise<void>}
*/
app.get('/:id/:z/:x/:y.:format', async (req, res) => { app.get('/:id/:z/:x/:y.:format', async (req, res) => {
if (verbose) {
console.log(req.params);
}
const item = repo[req.params.id]; const item = repo[req.params.id];
if (!item) { if (!item) {
return res.sendStatus(404); return res.sendStatus(404);
@ -88,7 +100,14 @@ export const serve_data = {
data = await gunzipP(data); data = await gunzipP(data);
isGzipped = false; isGzipped = false;
} }
data = options.dataDecoratorFunc(id, 'data', data, z, x, y); data = options.dataDecoratorFunc(
req.params.id,
'data',
data,
z,
x,
y,
);
} }
} }
@ -112,7 +131,9 @@ export const serve_data = {
} }
data = JSON.stringify(geojson); data = JSON.stringify(geojson);
} }
delete headers['ETag']; // do not trust the tile ETag -- regenerate if (headers) {
delete headers['ETag'];
}
headers['Content-Encoding'] = 'gzip'; headers['Content-Encoding'] = 'gzip';
res.set(headers); res.set(headers);
@ -123,6 +144,16 @@ export const serve_data = {
return res.status(200).send(data); return res.status(200).send(data);
}); });
/**
* Handles requests for elevation data.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @param {string} req.params.id - ID of the elevation data.
* @param {string} req.params.z - Z coordinate of the tile.
* @param {string} req.params.x - X coordinate of the tile (either integer or float).
* @param {string} req.params.y - Y coordinate of the tile (either integer or float).
* @returns {Promise<void>}
*/
app.get('/:id/elevation/:z/:x/:y', async (req, res, next) => { app.get('/:id/elevation/:z/:x/:y', async (req, res, next) => {
try { try {
const item = repo?.[req.params.id]; const item = repo?.[req.params.id];
@ -189,6 +220,7 @@ export const serve_data = {
const { minX, minY } = new SphericalMercator().xyz(tileCenter, z); const { minX, minY } = new SphericalMercator().xyz(tileCenter, z);
xy = [minX, minY]; xy = [minX, minY];
} }
const fetchTile = await fetchTileData(source, sourceType, z, x, y); const fetchTile = await fetchTileData(source, sourceType, z, x, y);
if (fetchTile == null) return res.status(204).send(); if (fetchTile == null) return res.status(204).send();
@ -259,6 +291,13 @@ export const serve_data = {
} }
}); });
/**
* Handles requests for metadata for the tiles.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @param {string} req.params.id - ID of the data source.
* @returns {Promise<void>}
*/
app.get('/:id.json', (req, res) => { app.get('/:id.json', (req, res) => {
const item = repo[req.params.id]; const item = repo[req.params.id];
if (!item) { if (!item) {
@ -289,6 +328,9 @@ export const serve_data = {
* @param {object} params Parameters object. * @param {object} params Parameters object.
* @param {string} id ID of the data source. * @param {string} id ID of the data source.
* @param {object} programOpts - An object containing the program options * @param {object} programOpts - An object containing the program options
* @param {string} programOpts.publicUrl Public URL for the data.
* @param {boolean} programOpts.verbose Whether verbose logging should be used.
* @param {Function} dataResolver Function to resolve data.
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
add: async function (options, repo, params, id, programOpts) { add: async function (options, repo, params, id, programOpts) {

View file

@ -8,9 +8,11 @@ import { getFontsPbf, listFonts } from './utils.js';
* Initializes and returns an Express app that serves font files. * Initializes and returns an Express app that serves font files.
* @param {object} options - Configuration options for the server. * @param {object} options - Configuration options for the server.
* @param {object} allowedFonts - An object containing allowed fonts. * @param {object} allowedFonts - An object containing allowed fonts.
* @param {object} programOpts - An object containing the program options.
* @returns {Promise<express.Application>} - A promise that resolves to the Express app. * @returns {Promise<express.Application>} - A promise that resolves to the Express app.
*/ */
export async function serve_font(options, allowedFonts) { export async function serve_font(options, allowedFonts, programOpts) {
const { verbose } = programOpts;
const app = express().disable('x-powered-by'); const app = express().disable('x-powered-by');
const lastModified = new Date().toUTCString(); const lastModified = new Date().toUTCString();
@ -19,7 +21,18 @@ export async function serve_font(options, allowedFonts) {
const existingFonts = {}; const existingFonts = {};
/**
* Handles requests for a font file.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @param {string} req.params.fontstack - Name of the font stack.
* @param {string} req.params.range - The range of the font (e.g. 0-255).
* @returns {Promise<void>}
*/
app.get('/fonts/:fontstack/:range.pbf', async (req, res) => { app.get('/fonts/:fontstack/:range.pbf', async (req, res) => {
if (verbose) {
console.log(req.params);
}
const fontstack = decodeURI(req.params.fontstack); const fontstack = decodeURI(req.params.fontstack);
const range = req.params.range; const range = req.params.range;
@ -41,6 +54,12 @@ export async function serve_font(options, allowedFonts) {
} }
}); });
/**
* Handles requests for a list of all available fonts.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @returns {void}
*/
app.get('/fonts.json', (req, res) => { app.get('/fonts.json', (req, res) => {
res.header('Content-type', 'application/json'); res.header('Content-type', 'application/json');
return res.send( return res.send(

View file

@ -3,7 +3,7 @@
'use strict'; 'use strict';
export const serve_rendered = { export const serve_rendered = {
init: (options, repo) => {}, init: (options, repo, programOpts) => {},
add: (options, repo, params, id, publicUrl, dataResolver) => {}, add: (options, repo, params, id, programOpts, dataResolver) => {},
remove: (repo, id) => {}, remove: (repo, id) => {},
}; };

View file

@ -267,7 +267,6 @@ function extractPathsFromQuery(query, transformer) {
} }
return paths; return paths;
} }
/** /**
* Parses marker options provided via query and sets corresponding attributes * Parses marker options provided via query and sets corresponding attributes
* on marker object. * on marker object.
@ -626,6 +625,13 @@ const respondImage = async (
* @param {object} options - Configuration options for the server. * @param {object} options - Configuration options for the server.
* @param {object} repo - The repository object holding style data. * @param {object} repo - The repository object holding style data.
* @param {object} req - Express request object. * @param {object} req - Express request object.
* @param {string} req.params.id - The id of the style.
* @param {string} req.params.p1 - The tile size parameter, if available.
* @param {string} req.params.p2 - The z parameter.
* @param {string} req.params.p3 - The x parameter.
* @param {string} req.params.p4 - The y parameter.
* @param {string} req.params.scale - The scale parameter.
* @param {string} req.params.format - The format of the image.
* @param {object} res - Express response object. * @param {object} res - Express response object.
* @param {Function} next - Express next middleware function. * @param {Function} next - Express next middleware function.
* @param {number} maxScaleFactor - The maximum scale factor allowed. * @param {number} maxScaleFactor - The maximum scale factor allowed.
@ -641,12 +647,12 @@ async function handleTileRequest(
) { ) {
const { const {
id, id,
p1: tileSize,
p2: zParam, p2: zParam,
p3: xParam, p3: xParam,
p4: yParam, p4: yParam,
scale: scaleParam, scale: scaleParam,
format, format,
p1: tileSize,
} = req.params; } = req.params;
const item = repo[id]; const item = repo[id];
if (!item) { if (!item) {
@ -694,6 +700,12 @@ async function handleTileRequest(
* @param {object} repo - The repository object holding style data. * @param {object} repo - The repository object holding style data.
* @param {object} req - Express request object. * @param {object} req - Express request object.
* @param {object} res - Express response object. * @param {object} res - Express response object.
* @param {string} req.params.p2 - The raw or static parameter.
* @param {string} req.params.p3 - The staticType parameter.
* @param {string} req.params.p4 - The width parameter.
* @param {string} req.params.p5 - The height parameter.
* @param {string} req.params.scale - The scale parameter.
* @param {string} req.params.format - The format of the image.
* @param {Function} next - Express next middleware function. * @param {Function} next - Express next middleware function.
* @param {number} maxScaleFactor - The maximum scale factor allowed. * @param {number} maxScaleFactor - The maximum scale factor allowed.
* @returns {Promise<void>} * @returns {Promise<void>}
@ -708,32 +720,24 @@ async function handleStaticRequest(
) { ) {
const { const {
id, id,
scale: scaleParam,
format,
p2: raw, p2: raw,
p3: type, p3: staticType,
p4: width, p4: width,
p5: height, p5: height,
scale: scaleParam,
format,
} = req.params; } = req.params;
const item = repo[id]; const item = repo[id];
const parsedWidth = parseInt(width) || 512; const parsedWidth = parseInt(width) || 512;
const parsedHeight = parseInt(height) || 512; const parsedHeight = parseInt(height) || 512;
const scale = parseScale(scaleParam, maxScaleFactor); const scale = parseScale(scaleParam, maxScaleFactor);
let isRaw = raw !== undefined; let isRaw = raw === 'raw';
let staticType = type;
if (!staticType) {
//workaround for type when raw is not set
staticType = raw;
isRaw = false;
}
if (!item || !staticType || !format || !scale) { if (!item || !staticType || !format || !scale) {
return res.sendStatus(404); return res.sendStatus(404);
} }
const staticTypeMatch = staticType.match(staticTypeRegex); const staticTypeMatch = staticType.match(staticTypeRegex);
console.log(staticTypeMatch);
if (staticTypeMatch.groups.lon) { if (staticTypeMatch.groups.lon) {
// Center Based Static Image // Center Based Static Image
const z = parseFloat(staticTypeMatch.groups.zoom) || 0; const z = parseFloat(staticTypeMatch.groups.zoom) || 0;
@ -765,7 +769,7 @@ async function handleStaticRequest(
// prettier-ignore // prettier-ignore
return await respondImage( return await respondImage(
options, item, z, x, y, bearing, pitch, parsedWidth, parsedHeight, scale, format, res, overlay, 'static', options, item, z, x, y, bearing, pitch, parsedWidth, parsedHeight, scale, format, res, overlay, 'static',
); );
} else if (staticTypeMatch.groups.minx) { } else if (staticTypeMatch.groups.minx) {
// Area Based Static Image // Area Based Static Image
@ -800,12 +804,12 @@ async function handleStaticRequest(
const markers = extractMarkersFromQuery(req.query, options, transformer); const markers = extractMarkersFromQuery(req.query, options, transformer);
// prettier-ignore // prettier-ignore
const overlay = await renderOverlay( const overlay = await renderOverlay(
z, x, y, bearing, pitch, parsedWidth, parsedHeight, scale, paths, markers, req.query, z, x, y, bearing, pitch, parsedWidth, parsedHeight, scale, paths, markers, req.query,
); );
// prettier-ignore // prettier-ignore
return await respondImage( return await respondImage(
options, item, z, x, y, bearing, pitch, parsedWidth, parsedHeight, scale, format, res, overlay, 'static', options, item, z, x, y, bearing, pitch, parsedWidth, parsedHeight, scale, format, res, overlay, 'static',
); );
} else if (staticTypeMatch.groups.auto) { } else if (staticTypeMatch.groups.auto) {
// Area Static Image // Area Static Image
@ -859,12 +863,12 @@ async function handleStaticRequest(
// prettier-ignore // prettier-ignore
const overlay = await renderOverlay( const overlay = await renderOverlay(
z, x, y, bearing, pitch, parsedWidth, parsedHeight, scale, paths, markers, req.query, z, x, y, bearing, pitch, parsedWidth, parsedHeight, scale, paths, markers, req.query,
); );
// prettier-ignore // prettier-ignore
return await respondImage( return await respondImage(
options, item, z, x, y, bearing, pitch, parsedWidth, parsedHeight, scale, format, res, overlay, 'static', options, item, z, x, y, bearing, pitch, parsedWidth, parsedHeight, scale, format, res, overlay, 'static',
); );
} else { } else {
return res.sendStatus(404); return res.sendStatus(404);
@ -879,18 +883,37 @@ export const serve_rendered = {
* Initializes the serve_rendered module. * Initializes the serve_rendered module.
* @param {object} options Configuration options. * @param {object} options Configuration options.
* @param {object} repo Repository object. * @param {object} repo Repository object.
* @param {object} programOpts - An object containing the program options.
* @returns {Promise<express.Application>} A promise that resolves to the Express app. * @returns {Promise<express.Application>} A promise that resolves to the Express app.
*/ */
init: async function (options, repo) { init: async function (options, repo, programOpts) {
const { verbose } = programOpts;
maxScaleFactor = Math.min(Math.floor(options.maxScaleFactor || 3), 9); maxScaleFactor = Math.min(Math.floor(options.maxScaleFactor || 3), 9);
const app = express().disable('x-powered-by'); const app = express().disable('x-powered-by');
/**
* Handles requests for tile images.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @param {string} req.params.id - The id of the style.
* @param {string} req.params.p1 - The tile size or static parameter, if available
* @param {string} req.params.p2 - The z, static, or raw parameter.
* @param {string} req.params.p3 - The x or staticType parameter.
* @param {string} req.params.p4 - The y or width parameter.
* @param {string} req.params.p5 - The height parameter.
* @param {string} req.params.scale - The scale parameter.
* @param {string} req.params.format - The format of the image.
* @returns {Promise<void>}
*/
app.get( app.get(
`/:id{/:p1}/:p2/:p3/:p4{x:p5}{@:scale}{.:format}`, `/:id{/:p1}/:p2/:p3/:p4{x:p5}{@:scale}{.:format}`,
async (req, res, next) => { async (req, res, next) => {
try { try {
const { p2 } = req.params; if (verbose) {
if (p2 === 'static') { console.log(req.params);
}
const { p1, p2 } = req.params;
if ((!p1 && p2 === 'static') || (p1 === 'static' && p2 === 'raw')) {
// Route to static if p2 is static // Route to static if p2 is static
if (options.serveStaticMaps !== false) { if (options.serveStaticMaps !== false) {
return handleStaticRequest( return handleStaticRequest(
@ -920,6 +943,14 @@ export const serve_rendered = {
}, },
); );
/**
* Handles requests for tile json endpoint.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @param {string} req.params.id - The id of the tilejson
* @param {string} [req.params.tileSize] - The size of the tile, if specified.
* @returns {void}
*/
app.get('{/:tileSize}/:id.json', (req, res, next) => { app.get('{/:tileSize}/:id.json', (req, res, next) => {
const item = repo[req.params.id]; const item = repo[req.params.id];
if (!item) { if (!item) {

View file

@ -29,9 +29,11 @@ export const serve_style = {
* Initializes the serve_style module. * Initializes the serve_style module.
* @param {object} options Configuration options. * @param {object} options Configuration options.
* @param {object} repo Repository object. * @param {object} repo Repository object.
* @param {object} programOpts - An object containing the program options.
* @returns {express.Application} The initialized Express application. * @returns {express.Application} The initialized Express application.
*/ */
init: function (options, repo) { init: function (options, repo, programOpts) {
const { verbose } = programOpts;
const app = express().disable('x-powered-by'); const app = express().disable('x-powered-by');
app.get('/:id/style.json', (req, res, next) => { app.get('/:id/style.json', (req, res, next) => {
@ -64,6 +66,9 @@ export const serve_style = {
}); });
app.get(`/:id/sprite{/:spriteID}{@:scale}{.:format}`, (req, res, next) => { app.get(`/:id/sprite{/:spriteID}{@:scale}{.:format}`, (req, res, next) => {
if (verbose) {
console.log(req.params);
}
const { spriteID = 'default', id, format } = req.params; const { spriteID = 'default', id, format } = req.params;
const spriteScale = allowedSpriteScales(req.params.scale); const spriteScale = allowedSpriteScales(req.params.scale);

View file

@ -76,7 +76,7 @@ async function start(opts) {
config = JSON.parse(fs.readFileSync(configPath, 'utf8')); config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
} catch (e) { } catch (e) {
console.log('ERROR: Config file not found or invalid!'); console.log('ERROR: Config file not found or invalid!');
console.log(' See README.md for instructions and sample data.'); console.log(' See README.md for instructions and sample data.');
process.exit(1); process.exit(1);
} }
} }
@ -167,12 +167,12 @@ async function start(opts) {
app.use(cors()); app.use(cors());
} }
app.use('/data/', serve_data.init(options, serving.data)); app.use('/data/', serve_data.init(options, serving.data, opts));
app.use('/files/', express.static(paths.files)); app.use('/files/', express.static(paths.files));
app.use('/styles/', serve_style.init(options, serving.styles)); app.use('/styles/', serve_style.init(options, serving.styles, opts));
if (!isLight) { if (!isLight) {
startupPromises.push( startupPromises.push(
serve_rendered.init(options, serving.rendered).then((sub) => { serve_rendered.init(options, serving.rendered, opts).then((sub) => {
app.use('/styles/', sub); app.use('/styles/', sub);
}), }),
); );
@ -288,7 +288,7 @@ async function start(opts) {
addStyle(id, item, true, true); addStyle(id, item, true, true);
} }
startupPromises.push( startupPromises.push(
serve_font(options, serving.fonts).then((sub) => { serve_font(options, serving.fonts, opts).then((sub) => {
app.use('/', sub); app.use('/', sub);
}), }),
); );
@ -342,6 +342,13 @@ async function start(opts) {
} }
}); });
} }
/**
* Handles requests for a list of available styles.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @param {string} [req.query.key] - Optional API key.
* @returns {void}
*/
app.get('/styles.json', (req, res, next) => { app.get('/styles.json', (req, res, next) => {
const result = []; const result = [];
const query = req.query.key const query = req.query.key
@ -395,15 +402,35 @@ async function start(opts) {
return arr; return arr;
} }
/**
* Handles requests for a rendered tilejson endpoint.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @param {string} req.params.tileSize - Optional tile size parameter.
* @returns {void}
*/
app.get('{/:tileSize}/rendered.json', (req, res, next) => { app.get('{/:tileSize}/rendered.json', (req, res, next) => {
const tileSize = allowedTileSizes(req.params['tileSize']); const tileSize = allowedTileSizes(req.params['tileSize']);
res.send(addTileJSONs([], req, 'rendered', parseInt(tileSize, 10))); res.send(addTileJSONs([], req, 'rendered', parseInt(tileSize, 10)));
}); });
/**
* Handles requests for a data tilejson endpoint.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @returns {void}
*/
app.get('/data.json', (req, res) => { app.get('/data.json', (req, res) => {
res.send(addTileJSONs([], req, 'data', undefined)); res.send(addTileJSONs([], req, 'data', undefined));
}); });
/**
* Handles requests for a combined rendered and data tilejson endpoint.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @param {string} req.params.tileSize - Optional tile size parameter.
* @returns {void}
*/
app.get('{/:tileSize}/index.json', (req, res, next) => { app.get('{/:tileSize}/index.json', (req, res, next) => {
const tileSize = allowedTileSizes(req.params['tileSize']); const tileSize = allowedTileSizes(req.params['tileSize']);
res.send( res.send(
@ -421,6 +448,7 @@ async function start(opts) {
app.use('/', express.static(path.join(__dirname, '../public/resources'))); app.use('/', express.static(path.join(__dirname, '../public/resources')));
const templates = path.join(__dirname, '../public/templates'); const templates = path.join(__dirname, '../public/templates');
/** /**
* Serves a Handlebars template. * Serves a Handlebars template.
* @param {string} urlPath - The URL path to serve the template at * @param {string} urlPath - The URL path to serve the template at
@ -477,6 +505,12 @@ async function start(opts) {
} }
} }
/**
* Handles requests for the index page, providing a list of available styles and data.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @returns {void}
*/
serveTemplate('/', 'index', (req) => { serveTemplate('/', 'index', (req) => {
let styles = {}; let styles = {};
for (const id of Object.keys(serving.styles || {})) { for (const id of Object.keys(serving.styles || {})) {
@ -489,11 +523,15 @@ async function start(opts) {
if (style.serving_rendered) { if (style.serving_rendered) {
const { center } = style.serving_rendered.tileJSON; const { center } = style.serving_rendered.tileJSON;
if (center) { if (center) {
style.viewer_hash = `#${center[2]}/${center[1].toFixed(5)}/${center[0].toFixed(5)}`; style.viewer_hash = `#${center[2]}/${center[1].toFixed(
5,
)}/${center[0].toFixed(5)}`;
const centerPx = mercator.px([center[0], center[1]], center[2]); const centerPx = mercator.px([center[0], center[1]], center[2]);
// Set thumbnail default size to be 256px x 256px // Set thumbnail default size to be 256px x 256px
style.thumbnail = `${Math.floor(center[2])}/${Math.floor(centerPx[0] / 256)}/${Math.floor(centerPx[1] / 256)}.png`; style.thumbnail = `${Math.floor(center[2])}/${Math.floor(
centerPx[0] / 256,
)}/${Math.floor(centerPx[1] / 256)}.png`;
} }
const tileSize = 512; const tileSize = 512;
@ -549,7 +587,9 @@ async function start(opts) {
} }
if (center) { if (center) {
const centerPx = mercator.px([center[0], center[1]], center[2]); const centerPx = mercator.px([center[0], center[1]], center[2]);
data.thumbnail = `${Math.floor(center[2])}/${Math.floor(centerPx[0] / 256)}/${Math.floor(centerPx[1] / 256)}.${tileJSON.format}`; data.thumbnail = `${Math.floor(center[2])}/${Math.floor(
centerPx[0] / 256,
)}/${Math.floor(centerPx[1] / 256)}.${tileJSON.format}`;
} }
} }
@ -574,6 +614,13 @@ async function start(opts) {
}; };
}); });
/**
* Handles requests for a map viewer template for a specific style.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @param {string} req.params.id - ID of the style.
* @returns {void}
*/
serveTemplate('/styles/:id/', 'viewer', (req) => { serveTemplate('/styles/:id/', 'viewer', (req) => {
const { id } = req.params; const { id } = req.params;
const style = clone(((serving.styles || {})[id] || {}).styleJSON); const style = clone(((serving.styles || {})[id] || {}).styleJSON);
@ -590,6 +637,13 @@ async function start(opts) {
}; };
}); });
/**
* Handles requests for a Web Map Tile Service (WMTS) XML template.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @param {string} req.params.id - ID of the style.
* @returns {void}
*/
serveTemplate('/styles/:id/wmts.xml', 'wmts', (req) => { serveTemplate('/styles/:id/wmts.xml', 'wmts', (req) => {
const { id } = req.params; const { id } = req.params;
const wmts = clone((serving.styles || {})[id]); const wmts = clone((serving.styles || {})[id]);
@ -621,6 +675,14 @@ async function start(opts) {
}; };
}); });
/**
* Handles requests for a data view template for a specific data source.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @param {string} req.params.id - ID of the data source.
* @param {string} [req.params.view] - Optional view type.
* @returns {void}
*/
serveTemplate('/data{/:view}/:id/', 'data', (req) => { serveTemplate('/data{/:view}/:id/', 'data', (req) => {
const { id, view } = req.params; const { id, view } = req.params;
const data = serving.data[id]; const data = serving.data[id];
@ -649,6 +711,12 @@ async function start(opts) {
startupComplete = true; startupComplete = true;
}); });
/**
* Handles requests to see the health of the server.
* @param {object} req - Express request object.
* @param {object} res - Express response object.
* @returns {void}
*/
app.get('/health', (req, res) => { app.get('/health', (req, res) => {
if (startupComplete) { if (startupComplete) {
return res.status(200).send('OK'); return res.status(200).send('OK');
@ -678,7 +746,6 @@ async function start(opts) {
startupPromise, startupPromise,
}; };
} }
/** /**
* Stop the server gracefully * Stop the server gracefully
* @param {string} signal Name of the received signal * @param {string} signal Name of the received signal