From 3fedd5bb77236ae169386699891308f2a862566e Mon Sep 17 00:00:00 2001 From: acalcutt Date: Sun, 5 Jan 2025 01:01:21 -0500 Subject: [PATCH] Revert "Update serve_style.js" This reverts commit 0f3629c75287a098e2294d30cd57ed5cdb9fc186. --- src/serve_style.js | 115 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 24 deletions(-) diff --git a/src/serve_style.js b/src/serve_style.js index 5dcdbe513..36975ec5d 100644 --- a/src/serve_style.js +++ b/src/serve_style.js @@ -91,36 +91,103 @@ export const serve_style = { }); /** - * 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). + * Handles GET requests for sprite images and JSON files. + * @param {express.Request} req - Express request object. + * @param {express.Response} res - Express response object. + * @param {express.NextFunction} next - Express next function. + * @param {string} req.params.id - ID of the sprite. + * @param {string} [req.params.spriteID='default'] - ID of the specific sprite image, defaults to 'default'. + * @param {string} [req.params.scale] - Scale of the sprite image, defaults to ''. + * @param {string} req.params.format - Format of the sprite file, 'png' or 'json'. * @returns {Promise} */ - app.get('/fonts/:fontstack/:range.pbf', async (req, res) => { + app.get(`/:id/sprite{/:spriteID}{@:scale}{.:format}`, (req, res, next) => { + const { spriteID = 'default', id, format, scale } = req.params; + const sanitizedId = String(id).replace(/\n|\r/g, ''); + const sanitizedScale = scale ? String(scale).replace(/\n|\r/g, '') : ''; + const sanitizedSpriteID = String(spriteID).replace(/\n|\r/g, ''); + const sanitizedFormat = format + ? '.' + String(format).replace(/\n|\r/g, '') + : ''; if (verbose) { - console.log(req.params); - } - const fontstack = decodeURI(req.params.fontstack); - const range = req.params.range; - - try { - const concatenated = await getFontsPbf( - options.serveAllFonts ? null : allowedFonts, - fontPath, - fontstack, - range, - existingFonts, + console.log( + `Handling sprite request for: /styles/%s/sprite/%s%s%s`, + sanitizedId, + sanitizedSpriteID, + sanitizedScale, + sanitizedFormat, ); + } + const item = repo[id]; + const validatedFormat = allowedSpriteFormats(format); + if (!item || !validatedFormat) { + if (verbose) + console.error( + `Sprite item or format not found for: /styles/%s/sprite/%s%s%s`, + sanitizedId, + sanitizedSpriteID, + sanitizedScale, + sanitizedFormat, + ); + return res.sendStatus(404); + } + const sprite = item.spritePaths.find((sprite) => sprite.id === spriteID); + const spriteScale = allowedSpriteScales(scale); + if (!sprite || spriteScale === null) { + if (verbose) + console.error( + `Bad Sprite ID or Scale for: /styles/%s/sprite/%s%s%s`, + sanitizedId, + sanitizedSpriteID, + sanitizedScale, + sanitizedFormat, + ); + return res.status(400).send('Bad Sprite ID or Scale'); + } - res.header('Content-type', 'application/x-protobuf'); - res.header('Last-Modified', lastModified); - return res.send(concatenated); - } catch (err) { - console.error('Error serving font:', err); - return res.status(400).header('Content-Type', 'text/plain').send(err); + const modifiedSince = req.get('if-modified-since'); + const cc = req.get('cache-control'); + if (modifiedSince && (!cc || cc.indexOf('no-cache') === -1)) { + if ( + new Date(item.lastModified).getTime() === + new Date(modifiedSince).getTime() + ) { + return res.sendStatus(304); + } } + + const sanitizedSpritePath = sprite.path.replace(/^(\.\.\/)+/, ''); + const filename = `${sanitizedSpritePath}${spriteScale}.${validatedFormat}`; + if (verbose) console.log(`Loading sprite from: %s`, filename); + + // eslint-disable-next-line security/detect-non-literal-fs-filename + fs.readFile(filename, (err, data) => { + if (err) { + if (verbose) + console.error( + 'Sprite load error: %s, Error: %s', + filename, + String(err), + ); + return res.sendStatus(404); + } + + if (validatedFormat === 'json') { + res.header('Content-type', 'application/json'); + } else if (validatedFormat === 'png') { + res.header('Content-type', 'image/png'); + } + if (verbose) + console.log( + `Responding with sprite data for /styles/%s/sprite/%s%s%s`, + sanitizedId, + sanitizedSpriteID, + sanitizedScale, + sanitizedFormat, + ); + res.set({ 'Last-Modified': item.lastModified }); + return res.send(data); + }); }); return app;