From d759dd2952ce28d94f9e86da6e558b5703c3cfef Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 27 Sep 2023 05:53:16 +0200 Subject: [PATCH] fix: incorrect polyline decoding (#993) * fix: incorrect polyline decoding Don't split static image encoded path on pipe or comma Signed-off-by: boldtrn * fix: still allow other parameters other than enc: That way we can still style individual paths Signed-off-by: boldtrn * chore: lint Signed-off-by: Andrew Calcutt * chore: lint + comment Signed-off-by: Andrew Calcutt * docs: try to clarify path information Signed-off-by: Andrew Calcutt * fix: stroke color not working unless path is specified i found this issue testing encoded paths. If width is not specifed, stroke color does not work Signed-off-by: Andrew Calcutt * docs: show different options Signed-off-by: Andrew Calcutt --------- Signed-off-by: boldtrn Signed-off-by: Andrew Calcutt Co-authored-by: Andrew Calcutt --- docs/endpoints.rst | 15 ++++++++------- src/serve_rendered.js | 25 ++++++++----------------- test/static.js | 12 ++++++++++++ 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/docs/endpoints.rst b/docs/endpoints.rst index 0eb8dcb..ef14aed 100644 --- a/docs/endpoints.rst +++ b/docs/endpoints.rst @@ -35,13 +35,14 @@ Static images * All the static image endpoints additionally support following query parameters: - * ``path`` - comma-separated ``lng,lat``, pipe-separated pairs - - * e.g. ``5.9,45.8|5.9,47.8|10.5,47.8|10.5,45.8|5.9,45.8`` - * can be provided multiple times - * or pass the path as per `Maptiler Cloud API `_ - * Match pattern: ((fill|stroke|width)\:[^\|]+\|)*((enc:.+)|((-?\d+\.?\d*,-?\d+\.?\d*\|)+(-?\d+\.?\d*,-?\d+\.?\d*))) - + * ``path`` + * can be provided multiple times + * syntax + * comma-separated ``lng,lat``, pipe-separated pairs + * e.g. ``path=5.9,45.8|5.9,47.8|10.5,47.8|10.5,45.8|5.9,45.8`` + * Match pattern with options ``((fill|stroke|width)\:[^\|]+\|)*((enc:.+)|((-?\d+\.?\d*,-?\d+\.?\d*\|)+(-?\d+\.?\d*,-?\d+\.?\d*)))`` + * e.g. ``path=stroke:yellow|width:2|fill:green|5.9,45.8|5.9,47.8|10.5,47.8|10.5,45.8|5.9,45.8`` or ``stroke:blue|enc:_p~iF~ps|U_ulLnnqC_mqNvxq`@`` + * 'enc:' is specified in `Google Encoded Polyline Format `. If used, the rest of the path parameter is considered to be part of the encoded polyline string -- do not specify the coordinate pairs. * ``latlng`` - indicates coordinates are in ``lat,lng`` order rather than the usual ``lng,lat`` * ``fill`` - color to use as the fill (e.g. ``red``, ``rgba(255,255,255,0.5)``, ``#0000ff``) * ``stroke`` - color of the path stroke diff --git a/src/serve_rendered.js b/src/serve_rendered.js index ee0a5b7..fc9982f 100644 --- a/src/serve_rendered.js +++ b/src/serve_rendered.js @@ -162,21 +162,12 @@ const extractPathsFromQuery = (query, transformer) => { providedPath.includes('enc:') && PATH_PATTERN.test(decodeURIComponent(providedPath)) ) { - const encodedPaths = providedPath.split(','); - for (const path of encodedPaths) { - const line = path - .split('|') - .filter( - (x) => - !x.startsWith('fill') && - !x.startsWith('stroke') && - !x.startsWith('width'), - ) - .join('') - .replace('enc:', ''); - const coords = polyline.decode(line).map(([lat, lng]) => [lng, lat]); - paths.push(coords); - } + // +4 because 'enc:' is 4 characters, everything after 'enc:' is considered to be part of the polyline + const encIndex = providedPath.indexOf('enc:') + 4; + const coords = polyline + .decode(providedPath.substring(encIndex)) + .map(([lat, lng]) => [lng, lat]); + paths.push(coords); } else { // Iterate through paths, parse and validate them const currentPath = []; @@ -520,8 +511,8 @@ const drawPath = (ctx, path, query, pathQuery, z) => { if ('stroke' in query) { ctx.strokeStyle = query.stroke; } - // Path Width gets higher priority - if (pathHasWidth) { + // Path Stroke gets higher priority + if (pathHasStroke) { ctx.strokeStyle = splitPaths .find((x) => x.startsWith('stroke:')) .replace('stroke:', ''); diff --git a/test/static.js b/test/static.js index 547d673..302becb 100644 --- a/test/static.js +++ b/test/static.js @@ -171,6 +171,18 @@ describe('Static endpoints', function () { '?path=-10,-10|-20,-20', ); }); + + describe('encoded path', function () { + testStatic( + prefix, + 'auto/20x20', + 'png', + 200, + 2, + /image\/png/, + '?path=' + decodeURIComponent('enc:{{biGwvyGoUi@s_A|{@'), + ); + }); }); describe('invalid requests return 4xx', function () {