From 4f530259bcdb339ea5fbfe71470330f1c4ffa1bc Mon Sep 17 00:00:00 2001 From: tebben Date: Thu, 10 Oct 2024 11:29:21 +0200 Subject: [PATCH] fix(source): support urls already containing query parameters for wms, wmts, and wfs --- src/Source/WFSSource.js | 25 ++++++++++++------------- src/Source/WMSSource.js | 29 +++++++++++++++-------------- src/Source/WMTSSource.js | 28 ++++++++++++++-------------- test/unit/dataSourceProvider.js | 10 +++++----- test/unit/source.js | 6 +++--- 5 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/Source/WFSSource.js b/src/Source/WFSSource.js index 60d346c657..73471dbb35 100644 --- a/src/Source/WFSSource.js +++ b/src/Source/WFSSource.js @@ -125,26 +125,25 @@ class WFSSource extends Source { this.typeName = source.typeName; this.version = source.version || '2.0.2'; this.bboxDigits = source.bboxDigits; - - // Add ? at the end of the url if it is not already in the given URL - if (!this.url.endsWith('?')) { - this.url = `${this.url}?`; - } - this.url = `${source.url - }SERVICE=WFS&REQUEST=GetFeature&typeName=${this.typeName - }&VERSION=${this.version - }&SRSNAME=${this.crs - }&outputFormat=${this.format - }&BBOX=%bbox,${this.crs}`; - this.zoom = { min: 0, max: Infinity }; + const urlObj = new URL(source.url); + urlObj.searchParams.set('SERVICE', 'WFS'); + urlObj.searchParams.set('REQUEST', 'GetFeature'); + urlObj.searchParams.set('typeName', this.typeName); + urlObj.searchParams.set('VERSION', this.version); + urlObj.searchParams.set('SRSNAME', this.crs); + urlObj.searchParams.set('outputFormat', this.format); + urlObj.searchParams.set('BBOX', `%bbox,${this.crs}`); + this.vendorSpecific = source.vendorSpecific; for (const name in this.vendorSpecific) { if (Object.prototype.hasOwnProperty.call(this.vendorSpecific, name)) { - this.url = `${this.url}&${name}=${this.vendorSpecific[name]}`; + urlObj.searchParams.set(name, this.vendorSpecific[name]); } } + + this.url = decodeURIComponent(urlObj.toString()); } handlingError(err) { diff --git a/src/Source/WMSSource.js b/src/Source/WMSSource.js index 0f5d9c8645..16050a87bc 100644 --- a/src/Source/WMSSource.js +++ b/src/Source/WMSSource.js @@ -116,26 +116,27 @@ class WMSSource extends Source { const crsPropName = (this.version === '1.3.0') ? 'CRS' : 'SRS'; - // Add ? at the end of the url if it is not already in the given URL - if (!this.url.endsWith('?')) { - this.url = `${this.url}?`; - } - this.url = `${this.url}SERVICE=WMS&REQUEST=GetMap&LAYERS=${ - this.name}&VERSION=${ - this.version}&STYLES=${ - this.style}&FORMAT=${ - this.format}&TRANSPARENT=${ - this.transparent}&BBOX=%bbox&${ - crsPropName}=${ - this.crs}&WIDTH=${this.width}&HEIGHT=${this.height}`; - + const urlObj = new URL(this.url); + urlObj.searchParams.set('SERVICE', 'WMS'); + urlObj.searchParams.set('REQUEST', 'GetMap'); + urlObj.searchParams.set('LAYERS', this.name); + urlObj.searchParams.set('VERSION', this.version); + urlObj.searchParams.set('STYLES', this.style); + urlObj.searchParams.set('FORMAT', this.format); + urlObj.searchParams.set('TRANSPARENT', this.transparent); + urlObj.searchParams.set('BBOX', '%bbox'); + urlObj.searchParams.set(crsPropName, this.crs); + urlObj.searchParams.set('WIDTH', this.width); + urlObj.searchParams.set('HEIGHT', this.height); this.vendorSpecific = source.vendorSpecific; for (const name in this.vendorSpecific) { if (Object.prototype.hasOwnProperty.call(this.vendorSpecific, name)) { - this.url = `${this.url}&${name}=${this.vendorSpecific[name]}`; + urlObj.searchParams.set(name, this.vendorSpecific[name]); } } + + this.url = decodeURIComponent(urlObj.toString()); } urlFromExtent(extentOrTile) { diff --git a/src/Source/WMTSSource.js b/src/Source/WMTSSource.js index 40d0c17685..62ee8ea245 100644 --- a/src/Source/WMTSSource.js +++ b/src/Source/WMTSSource.js @@ -72,26 +72,26 @@ class WMTSSource extends TMSSource { this.isWMTSSource = true; - // Add ? at the end of the url if it is not already in the given URL - if (!this.url.endsWith('?')) { - this.url = `${this.url}?`; - } - this.url = `${this.url}` + - `LAYER=${source.name}` + - `&FORMAT=${this.format}` + - '&SERVICE=WMTS' + - `&VERSION=${source.version || '1.0.0'}` + - '&REQUEST=GetTile' + - `&STYLE=${source.style || 'normal'}` + - `&TILEMATRIXSET=${source.tileMatrixSet}` + - '&TILEMATRIX=%TILEMATRIX&TILEROW=%ROW&TILECOL=%COL'; + const urlObj = new URL(this.url); + urlObj.searchParams.set('LAYER', source.name); + urlObj.searchParams.set('FORMAT', this.format); + urlObj.searchParams.set('SERVICE', 'WMTS'); + urlObj.searchParams.set('VERSION', source.version || '1.0.0'); + urlObj.searchParams.set('REQUEST', 'GetTile'); + urlObj.searchParams.set('STYLE', source.style || 'normal'); + urlObj.searchParams.set('TILEMATRIXSET', source.tileMatrixSet); + urlObj.searchParams.set('TILEMATRIX', '%TILEMATRIX'); + urlObj.searchParams.set('TILEROW', '%ROW'); + urlObj.searchParams.set('TILECOL', '%COL'); this.vendorSpecific = source.vendorSpecific; for (const name in this.vendorSpecific) { if (Object.prototype.hasOwnProperty.call(this.vendorSpecific, name)) { - this.url = `${this.url}&${name}=${this.vendorSpecific[name]}`; + urlObj.searchParams.set(name, this.vendorSpecific[name]); } } + + this.url = decodeURIComponent(urlObj.toString()); } } diff --git a/test/unit/dataSourceProvider.js b/test/unit/dataSourceProvider.js index 93910d6f7a..9ba251069d 100644 --- a/test/unit/dataSourceProvider.js +++ b/test/unit/dataSourceProvider.js @@ -98,7 +98,7 @@ describe('Provide in Sources', function () { }); featureLayer.source = new WFSSource({ - url: 'http://', + url: 'http://domain.com', typeName: 'name', format: 'application/json', extent: globalExtent, @@ -128,7 +128,7 @@ describe('Provide in Sources', function () { it('should get wmts texture with DataSourceProvider', (done) => { colorlayer.source = new WMTSSource({ - url: 'http://', + url: 'http://domain.com', name: 'name', format: 'image/png', tileMatrixSet: 'PM', @@ -159,7 +159,7 @@ describe('Provide in Sources', function () { it('should get wmts texture elevation with DataSourceProvider', (done) => { elevationlayer.source = new WMTSSource({ - url: 'http://', + url: 'http://domain.com', name: 'name', format: 'image/png', tileMatrixSet: 'PM', @@ -188,7 +188,7 @@ describe('Provide in Sources', function () { it('should get wms texture with DataSourceProvider', (done) => { colorlayer.source = new WMSSource({ - url: 'http://', + url: 'http://domain.com', name: 'name', format: 'image/png', extent: globalExtent, @@ -320,7 +320,7 @@ describe('Provide in Sources', function () { it('should get updated RasterLayer', (done) => { colorlayer.source = new WMTSSource({ - url: 'http://', + url: 'http://domain.com', name: 'name', format: 'image/png', tileMatrixSet: 'PM', diff --git a/test/unit/source.js b/test/unit/source.js index 6014e877a3..2a3a404d06 100644 --- a/test/unit/source.js +++ b/test/unit/source.js @@ -44,7 +44,7 @@ describe('Sources', function () { describe('WFSSource', function () { const paramsWFS = { - url: 'http://', + url: 'http://domain.com', typeName: 'test', crs: 'EPSG:4326', }; @@ -93,7 +93,7 @@ describe('Sources', function () { describe('WMTSSource', function () { const paramsWMTS = { - url: 'http://', + url: 'http://domain.com', name: 'name', crs: 'EPSG:4326', tileMatrixSet: 'PM', @@ -141,7 +141,7 @@ describe('Sources', function () { describe('WMSSource', function () { const paramsWMS = { - url: 'http://', + url: 'http://domain.com', name: 'name', extent: [-90, 90, -45, 45], crs: 'EPSG:4326',