diff --git a/projects/hslayers-server/src/proxy.js b/projects/hslayers-server/src/proxy.js index f36ee830a5..2dd5e39fda 100644 --- a/projects/hslayers-server/src/proxy.js +++ b/projects/hslayers-server/src/proxy.js @@ -25,7 +25,6 @@ const cors_proxy = cors_anywhere.createServer({ const GEONAMES_APIKEY = process.env.HS_GEONAMES_API_KEY || 'hslayersng'; createServer((req, res) => { - console.log('🚀 ~ .createServer ~ req:', req.url, req.headers); try { if (req.url == '' || req.url == '/') { res.write('HSLayers server proxy
'); @@ -33,19 +32,9 @@ createServer((req, res) => { res.end(); } else { req.url = decodeURIComponent(req.url); + req.url = encodeUrlPathAndParams(req.url); const [base, tld, pathAndQueryParams] = splitUrlAtTld(req.url); - console.log('🚀 ~ .createServer ~ base, tld, pathAndQueryParams:', base, tld, pathAndQueryParams); - const encodedPath = pathAndQueryParams.split('?')[0].split('/').map(segment => encodeURIComponent(segment)) const params = parseQuerystring(pathAndQueryParams.split('?')[1]); - req.url = - base + - '.' + - tld + - '/' + - encodedPath.join('/') + - (Object.keys(params).length == 0 ? '' : '?') + - encodeQuerystring(params); - console.log('🚀 ~ .createServer ~ req.url after process:', req.url); if (base.includes('api.geonames') && tld === 'org' && pathAndQueryParams.startsWith('searchJSON')) { if ( typeof params.provider == 'undefined' || @@ -59,7 +48,6 @@ createServer((req, res) => { if (base.includes('api.openrouteservice') && tld == 'org') { req.headers.authorization = process.env.OPENROUTESERVICE_API_KEY; } - cors_proxy.emit('request', req, res); } } catch (ex) { @@ -124,3 +112,22 @@ export const splitUrlAtTld = (url) => { ]; } } + +/** + * Takes a decoded URL, splits it into parts and encodes its path and search strings + * but leaves the host name untouched + * @param {string} url URL + * @returns partially encoded URL + */ +export const encodeUrlPathAndParams = (url) => { + const [base, tld, pathAndQueryParams] = splitUrlAtTld(url); + const encodedPath = pathAndQueryParams.split('?')[0].split('/').map(segment => encodeURIComponent(segment)) + const params = parseQuerystring(pathAndQueryParams.split('?')[1]); + return base + + '.' + + tld + + '/' + + encodedPath.join('/') + + (Object.keys(params).length == 0 ? '' : '?') + + encodeQuerystring(params); +} diff --git a/projects/hslayers-server/test/proxy.spec.js b/projects/hslayers-server/test/proxy.spec.js index 47f7c3155e..055752e3c0 100644 --- a/projects/hslayers-server/test/proxy.spec.js +++ b/projects/hslayers-server/test/proxy.spec.js @@ -1,49 +1,48 @@ import { expect } from 'chai'; -import { splitUrlAtTld } from '../src/proxy.js'; +import { splitUrlAtTld, encodeUrlPathAndParams } from '../src/proxy.js'; -describe('Proxy module', function () { - describe('#splitUrlAtTld()', function () { - it('should split to three parts on IP', function () { - const url = 'http://127.0.0.1:8085/https://ags.cuzk.cz/arcgis2/services/dmr4g/ImageServer/WMSServer?REQUEST=GetMap&SERVICE=WMS&VERSION=1.3.0&FORMAT=image/png&STYLES=default&TRANSPARENT=true&LAYERS=dmr4g:GrayscaleHillshade&WIDTH=256&HEIGHT=256&CRS=EPSG:3857&BBOX=1878516.4071364924,6574807.42497772,2191602.474992574,6887893.492833802' - const split = splitUrlAtTld(url); - expect(split).to.be.an.instanceOf(Array); - expect(split).to.have.length(3); - expect(split[0]).to.equal('http://127.0.0'); - expect(split[1]).to.equal('1:8085'); - expect(split[2]).to.equal('https://ags.cuzk.cz/arcgis2/services/dmr4g/ImageServer/WMSServer?REQUEST=GetMap&SERVICE=WMS&VERSION=1.3.0&FORMAT=image/png&STYLES=default&TRANSPARENT=true&LAYERS=dmr4g:GrayscaleHillshade&WIDTH=256&HEIGHT=256&CRS=EPSG:3857&BBOX=1878516.4071364924,6574807.42497772,2191602.474992574,6887893.492833802'); - }); +describe('Proxy module', function() { + describe('#splitUrlAtTld()', function() { - it('should split to three parts on h4e domain with ags.plzen.eu service containing diacritics', function () { - const url = 'https://hub4everybody.com/proxy/https://ags.plzen.eu/arcgis/rest/services/GIS_Historicke/GIS_HIS_Plzeň_1926/MapServer?f=json' - const split = splitUrlAtTld(url); - expect(split).to.be.an.instanceOf(Array); - expect(split).to.have.length(3); - expect(split[0]).to.equal('https://hub4everybody'); - expect(split[1]).to.equal('com'); - expect(split[2]).to.equal('https://ags.plzen.eu/arcgis/rest/services/GIS_Historicke/GIS_HIS_Plze%C5%88_1926/MapServer?f=json'); - }); + //The URL is supposed to be always relative to the proxy base (i.e. only the queried URL) - it('should split to three parts on h4e domain with ČÚZK service', function () { - const url = 'https://hub4everybody.com/proxy/https://ags.cuzk.cz/arcgis2/services/dmr4g/ImageServer/WMSServer?REQUEST=GetMap&SERVICE=WMS&VERSION=1.3.0&FORMAT=image/png&STYLES=default&TRANSPARENT=true&LAYERS=dmr4g:GrayscaleHillshade&WIDTH=256&HEIGHT=256&CRS=EPSG:3857&BBOX=1878516.4071364924,6574807.42497772,2191602.474992574,6887893.492833802' + it('should split to three parts with ČÚZK service', function() { + const url = '/https://ags.cuzk.cz/arcgis2/services/dmr4g/ImageServer/WMSServer?REQUEST=GetMap&SERVICE=WMS&VERSION=1.3.0&FORMAT=image/png&STYLES=default&TRANSPARENT=true&LAYERS=dmr4g:GrayscaleHillshade&WIDTH=256&HEIGHT=256&CRS=EPSG:3857&BBOX=1878516.4071364924,6574807.42497772,2191602.474992574,6887893.492833802' const split = splitUrlAtTld(url); expect(split).to.be.an.instanceOf(Array); expect(split).to.have.length(3); - expect(split[0]).to.equal('https://hub4everybody'); - expect(split[1]).to.equal('com'); - expect(split[2]).to.equal('https://ags.cuzk.cz/arcgis2/services/dmr4g/ImageServer/WMSServer?REQUEST=GetMap&SERVICE=WMS&VERSION=1.3.0&FORMAT=image/png&STYLES=default&TRANSPARENT=true&LAYERS=dmr4g:GrayscaleHillshade&WIDTH=256&HEIGHT=256&CRS=EPSG:3857&BBOX=1878516.4071364924,6574807.42497772,2191602.474992574,6887893.492833802'); + expect(split[0]).to.equal('/https://ags.cuzk'); + expect(split[1]).to.equal('cz'); + expect(split[2]).to.equal('arcgis2/services/dmr4g/ImageServer/WMSServer?REQUEST=GetMap&SERVICE=WMS&VERSION=1.3.0&FORMAT=image/png&STYLES=default&TRANSPARENT=true&LAYERS=dmr4g:GrayscaleHillshade&WIDTH=256&HEIGHT=256&CRS=EPSG:3857&BBOX=1878516.4071364924,6574807.42497772,2191602.474992574,6887893.492833802'); }); - it('should split to three parts on Watlas domain with ČÚZK service', function () { - const url = 'https://watlas.lesprojekt.cz/en/proxy/https://ags.cuzk.cz/arcgis2/services/dmr4g/ImageServer/WMSServer/?REQUEST=GetMap&SERVICE=WMS&VERSION=1.3.0&FORMAT=image/png&STYLES=default&TRANSPARENT=true&LAYERS=dmr4g:GrayscaleHillshade&WIDTH=256&HEIGHT=256&CRS=EPSG:3857&BBOX=1878516.4071364924,6574807.42497772,2191602.474992574,6887893.492833802' + it('should split to three parts with ags.plzen.eu service containing diacritics', function() { + const url = '/https://ags.plzen.eu/arcgis/rest/services/GIS_Historicke/GIS_HIS_Plzeň_1926/MapServer?f=json' const split = splitUrlAtTld(url); expect(split).to.be.an.instanceOf(Array); expect(split).to.have.length(3); - expect(split[0]).to.equal('https://watlas.lesprojekt'); - expect(split[1]).to.equal('cz'); - expect(split[2]).to.equal('https://ags.cuzk.cz/arcgis2/services/dmr4g/ImageServer/WMSServer/?REQUEST=GetMap&SERVICE=WMS&VERSION=1.3.0&FORMAT=image/png&STYLES=default&TRANSPARENT=true&LAYERS=dmr4g:GrayscaleHillshade&WIDTH=256&HEIGHT=256&CRS=EPSG:3857&BBOX=1878516.4071364924,6574807.42497772,2191602.474992574,6887893.492833802'); + expect(split[0]).to.equal('/https://ags.plzen'); + expect(split[1]).to.equal('eu'); + expect(split[2]).to.equal('arcgis/rest/services/GIS_Historicke/GIS_HIS_Plzeň_1926/MapServer?f=json'); }); // Add more test cases as needed }); + + describe('#encodeUrlPathAndParams()', function() { + it('should encode slashes, commas and colons in the search params', function() { + const url = '/https://ags.cuzk.cz/arcgis2/services/dmr4g/ImageServer/WMSServer?REQUEST=GetMap&SERVICE=WMS&VERSION=1.3.0&FORMAT=image/png&STYLES=default&TRANSPARENT=true&LAYERS=dmr4g:GrayscaleHillshade&WIDTH=256&HEIGHT=256&CRS=EPSG:3857&BBOX=1878516.4071364924,6574807.42497772,2191602.474992574,6887893.492833802'; + const safeUrl = encodeUrlPathAndParams(url); + expect(safeUrl).to.exist; + expect(safeUrl).to.equal('/https://ags.cuzk.cz/arcgis2/services/dmr4g/ImageServer/WMSServer?REQUEST=GetMap&SERVICE=WMS&VERSION=1.3.0&FORMAT=image%2Fpng&STYLES=default&TRANSPARENT=true&LAYERS=dmr4g%3AGrayscaleHillshade&WIDTH=256&HEIGHT=256&CRS=EPSG%3A3857&BBOX=1878516.4071364924%2C6574807.42497772%2C2191602.474992574%2C6887893.492833802'); + }) + + it('should encode letter ň in Plzeň in the URL path', function() { + const url = '/https://ags.plzen.eu/arcgis/rest/services/GIS_Historicke/GIS_HIS_Plzeň_1926/MapServer?f=json'; + const safeUrl = encodeUrlPathAndParams(url); + expect(safeUrl).to.exist; + expect(safeUrl).to.equal('/https://ags.plzen.eu/arcgis/rest/services/GIS_Historicke/GIS_HIS_Plze%C5%88_1926/MapServer?f=json'); + }) + }); });