Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions web/client/components/map/openlayers/plugins/WMSLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import VectorTileSource from 'ol/source/VectorTile';
import VectorTileLayer from 'ol/layer/VectorTile';

import { isVectorFormat } from '../../../../utils/VectorTileUtils';
import { isValidResponse } from '../../../../utils/WMSUtils';
import { isValidResponse, parseOGCException } from '../../../../utils/WMSUtils';
import { OL_VECTOR_FORMATS, applyStyle } from '../../../../utils/openlayers/VectorTileUtils';

import { proxySource, getWMSURLs, wmsToOpenlayersOptions, toOLAttributions, generateTileGrid } from '../../../../utils/openlayers/WMSUtils';
Expand Down Expand Up @@ -66,26 +66,25 @@ const loadFunction = (options, headers) => function(image, src) {
}
}
}).catch(e => {
image.setState(3);
console.error(e);
});
} else {
if (headers) {
if (headers) { // case of custom headers is setted in localConfig, example requestsConfigurationRules
axios.get(newSrc, {
headers,
responseType: 'blob'
}).then(response => {
if (isValidResponse(response)) {
}).then(async response => {
if (isValidResponse(response)) { // not contains OGC exception
image.getImage().src = URL.createObjectURL(response.data);
} else {
// #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);
const exception = await parseOGCException(response);
throw new Error('response exception: ' + exception);
}
}).catch(e => {
image.getImage().src = null;
console.error(e);
image.getImage().src = null; // needed to trigger the MS imageloaderror event in Map.onLayerError
image.setState(3); // set error state for tile and removed from the queue and will block, prevent reloading loops
console.error(e); // show ogc exception in console for debugging
});
} else {
img.src = newSrc;
Expand Down
29 changes: 29 additions & 0 deletions web/client/utils/WMSUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,35 @@ export const isValidResponse = (response) => {
return response?.status === 200 && response?.data && response?.data?.type !== "text/xml";
};

/**
* parse the xml exception message and code
* @param {Object} response is axios response object containing the exception in the data property is a Blob of type text/xml
* @returns {string} parsed exception with code and message
*/
export const parseOGCException = (response) => {
return new Promise((resolve, reject) => {
const textDecoder = new TextDecoder();
const reader = response.data.stream().getReader();
reader.read().then(({ done, value }) => {
if (done) {
reject("No data available");
return;
}
const responseText = textDecoder.decode(value);
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(responseText, "text/xml");
const serviceException = xmlDoc.getElementsByTagName("ServiceException")[0];
if (serviceException) {
const code = serviceException.getAttribute("code") || "unknown";
const message = serviceException.textContent || "unknown";
resolve(`code: ${code}, message: ${message}`);
} else {
resolve(`code: unknown, message: ${responseText}`);
}
}).catch(reject);
});
};

/**
* Parses layer info from capabilities object
* @param {object} capabilities capabilities section of the layer as an object from xml2js parsing of the WMS capabilities
Expand Down
15 changes: 14 additions & 1 deletion web/client/utils/__tests__/WMSUtils-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
getLayerOptions,
getTileGridFromLayerOptions,
getCustomTileGridProperties,
isValidResponse
isValidResponse,
parseOGCException
} from '../WMSUtils';

describe('Test the WMSUtils', () => {
Expand Down Expand Up @@ -132,4 +133,16 @@ describe('Test the WMSUtils', () => {
// valid responses
expect(isValidResponse({data: {type: "blob"}, status: 200})).toBeTruthy();
});
it('test parseOGCException', () => {
const response = {
data: new Blob([`<?xml version="1.0" encoding="UTF-8"?><ServiceExceptionReport version="1.3.0" xmlns="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc https://geoserver-d.eugeadev.iasp.tgscloud.net/geoserver/schemas/wms/1.3.0/exceptions_1_3_0.xsd"><ServiceException code="internalError">Rendering process failed. Layers: road_issue:Road</ServiceException></ServiceExceptionReport>`], { type: 'text/xml' }),
status: 200
};
expect(parseOGCException(response).then((result) => {
expect(result).toEqual({
code: 'internalError',
message: 'Rendering process failed. Layers: road_issue:Road'
});
}));
});
});
Loading