diff --git a/web/client/components/map/openlayers/__tests__/Layer-test.jsx b/web/client/components/map/openlayers/__tests__/Layer-test.jsx index 00886485a3..79da586f44 100644 --- a/web/client/components/map/openlayers/__tests__/Layer-test.jsx +++ b/web/client/components/map/openlayers/__tests__/Layer-test.jsx @@ -321,6 +321,37 @@ describe('Openlayers layer', () => { expect(layer).toBeTruthy(); expect(map.getLayers().getLength()).toBe(1); }); + it('render wms singleTile layer with error', (done) => { + mockAxios.onGet().reply(r => { + expect(r.url.indexOf('SAMPLE_URL') >= 0 ).toBeTruthy(); + return [200, "\n" + + "\n" + + " \n" + + " msWFSGetFeature(): WFS server error. Invalid GetFeature Request\n" + + " \n" + + ""]; + }); + const options = { + type: 'wms', + visibility: true, + singleTile: true, + url: 'SAMPLE_URL', + name: 'osm:vector_tile' + }; + const layer = ReactDOM.render(, document.getElementById("container")); + expect(layer.layer.getSource()).toBeTruthy(); + layer.layer.getSource().on('imageloaderror', (e)=> { + setTimeout(() => { + expect(e).toBeTruthy(); + done(); + }, 200); + }); + }); it('creates a tiled wms layer for openlayers map with long url', (done) => { let options = { "type": "wms", diff --git a/web/client/components/map/openlayers/plugins/WMSLayer.js b/web/client/components/map/openlayers/plugins/WMSLayer.js index 20d3e3fb5c..7cc6320cbc 100644 --- a/web/client/components/map/openlayers/plugins/WMSLayer.js +++ b/web/client/components/map/openlayers/plugins/WMSLayer.js @@ -30,6 +30,7 @@ import VectorTileSource from 'ol/source/VectorTile'; import VectorTileLayer from 'ol/layer/VectorTile'; import { isVectorFormat } from '../../../../utils/VectorTileUtils'; +import { isValidResponse } from '../../../../utils/WMSUtils'; import { OL_VECTOR_FORMATS, applyStyle } from '../../../../utils/openlayers/VectorTileUtils'; import { proxySource, getWMSURLs, wmsToOpenlayersOptions, toOLAttributions, generateTileGrid } from '../../../../utils/openlayers/WMSUtils'; @@ -74,10 +75,14 @@ const loadFunction = (options, headers) => function(image, src) { headers, responseType: 'blob' }).then(response => { - if (response.status === 200 && response.data) { + if (isValidResponse(response)) { image.getImage().src = URL.createObjectURL(response.data); } else { - console.error("Status code: " + response.status); + // #10701 this is needed to trigger the imageloaderror event + // in ol otherwise this event is not triggered if you assign + // the xml content of the exception to the src attribute + image.getImage().src = null; + console.error("error: " + response.data); } }).catch(e => { console.error(e); diff --git a/web/client/utils/WMSUtils.js b/web/client/utils/WMSUtils.js index 81439c2de4..9acd8a510b 100644 --- a/web/client/utils/WMSUtils.js +++ b/web/client/utils/WMSUtils.js @@ -46,6 +46,19 @@ export const isValidGetMapFormat = (format) => { export const isValidGetFeatureInfoFormat = (format) => { return getDefaultSupportedGetFeatureInfoFormats().includes(format); }; + +/** + * Validate GetMap response from WMS ImageWMS. + * "OGC protocol returns status = 200 with Exception in body, + * this function checks if the exception is contained in the response". + * https://docs.geoserver.org/main/en/user/services/wms/reference.html#exceptions + * @param {object} response + * @return {boolean} + */ +export const isValidResponse = (response) => { + return response?.status === 200 && response?.data && response?.data?.type !== "text/xml"; +}; + /** * Parses layer info from capabilities object * @param {object} capabilities capabilities section of the layer as an object from xml2js parsing of the WMS capabilities diff --git a/web/client/utils/__tests__/WMSUtils-test.js b/web/client/utils/__tests__/WMSUtils-test.js index 1784efd574..c72a0f2e5e 100644 --- a/web/client/utils/__tests__/WMSUtils-test.js +++ b/web/client/utils/__tests__/WMSUtils-test.js @@ -12,7 +12,8 @@ import { isValidGetFeatureInfoFormat, getLayerOptions, getTileGridFromLayerOptions, - getCustomTileGridProperties + getCustomTileGridProperties, + isValidResponse } from '../WMSUtils'; describe('Test the WMSUtils', () => { @@ -96,4 +97,12 @@ describe('Test the WMSUtils', () => { } }); }); + it('test isValidResponse', () => { + // invalid responses + expect(isValidResponse({data: {type: "text/xml"}})).toBeFalsy(); + expect(isValidResponse({data: {type: "blob"}})).toBeFalsy(); + expect(isValidResponse({data: {type: "blob"}, status: 401})).toBeFalsy(); + // valid responses + expect(isValidResponse({data: {type: "blob"}, status: 200})).toBeTruthy(); + }); });