diff --git a/src/legacy/core_plugins/tile_map/common/ems_client.js b/src/legacy/core_plugins/tile_map/common/ems_client.js index a66a6949951d0..45b756e9bd0c2 100644 --- a/src/legacy/core_plugins/tile_map/common/ems_client.js +++ b/src/legacy/core_plugins/tile_map/common/ems_client.js @@ -92,8 +92,10 @@ const unescapeTemplateVars = url => { const DEFAULT_LANGUAGE = 'en'; + export class EMSClientV66 { + EMS_LOAD_TIMEOUT = 32000; constructor({ kbnVersion, manifestServiceUrl, htmlSanitizer, language, landingPageUrl }) { @@ -103,7 +105,6 @@ export class EMSClientV66 { this._sanitizer = htmlSanitizer ? htmlSanitizer : x => x; this._manifestServiceUrl = manifestServiceUrl; - this._loadCatalogue = null; this._loadFileLayers = null; this._loadTMSServices = null; this._emsLandingPageUrl = landingPageUrl; @@ -125,11 +126,39 @@ export class EMSClientV66 { * this internal method is overridden by the tests to simulate custom manifest. */ async _getManifest(manifestUrl) { - const url = extendUrl(manifestUrl, { query: this._queryParams }); - const result = await fetch(url); - return await result.json(); + let result; + try { + const url = extendUrl(manifestUrl, { query: this._queryParams }); + result = await this._fetchWithTimeout(url); + } catch (e) { + if (!e) { + e = new Error('Unknown error'); + } + if (!(e instanceof Error)) { + e = new Error(e.data || `status ${e.statusText || e.status}`); + } + throw new Error(`Unable to retrieve manifest from ${manifestUrl}: ${e.message}`); + } finally { + return result + ? await result.json() + : null; + } } + _fetchWithTimeout(url) { + return new Promise( + (resolve, reject) => { + const timer = setTimeout( + () => reject(new Error(`Request to ${url} timed out`)), + this.EMS_LOAD_TIMEOUT + ); + fetch(url) + .then( + response => resolve(response), + err => reject(err) + ).finally(() => clearTimeout(timer)); + }); + } /** * Add optional query-parameters to all requests @@ -151,54 +180,42 @@ export class EMSClientV66 { _invalidateSettings() { - this._loadCatalogue = _.once(async () => { + this._getManifestWithParams = _.once( + async url => this._getManifest(this.extendUrlWithParams(url))); - try { - const url = this.extendUrlWithParams(this._manifestServiceUrl); - return await this._getManifest(url); - } catch (e) { - if (!e) { - e = new Error('Unknown error'); - } - if (!(e instanceof Error)) { - e = new Error(e.data || `status ${e.statusText || e.status}`); - } - throw new Error(`Could not retrieve manifest from the tile service: ${e.message}`); + this._getCatalogueService = async serviceType => { + const catalogueManifest = await this._getManifestWithParams(this._manifestServiceUrl); + let service; + if(_.has(catalogueManifest, 'services')) { + service = catalogueManifest.services + .find(s => s.type === serviceType); } - }); - - - this._loadFileLayers = _.once(async () => { + return service || {}; + }; - const catalogue = await this._loadCatalogue(); - const fileService = catalogue.services.find(service => service.type === 'file'); - if (!fileService) { - return []; + this._wrapServiceAttribute = async (manifestUrl, attr, WrapperClass) => { + const manifest = await this._getManifest(manifestUrl); + if (_.has(manifest, attr)) { + return manifest[attr].map(config => { + return new WrapperClass(config, this); + }); } + return []; + }; - const manifest = await this._getManifest(fileService.manifest, this._queryParams); - - return manifest.layers.map(layerConfig => { - return new FileLayer(layerConfig, this); - }); + this._loadFileLayers = _.once(async () => { + const fileService = await this._getCatalogueService('file'); + return _.isEmpty(fileService) + ? [] + : this._wrapServiceAttribute(fileService.manifest, 'layers', FileLayer); }); this._loadTMSServices = _.once(async () => { - - const catalogue = await this._loadCatalogue(); - const tmsService = catalogue.services.find((service) => service.type === 'tms'); - if (!tmsService) { - return []; - } - const tmsManifest = await this._getManifest(tmsService.manifest, this._queryParams); - - - return tmsManifest.services.map(serviceConfig => { - return new TMSService(serviceConfig, this); - }); - + const tmsService = await this._getCatalogueService('tms'); + return _.isEmpty(tmsService) + ? [] + : await this._wrapServiceAttribute(tmsService.manifest, 'services', TMSService); }); - } getLandingPageUrl() { diff --git a/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js b/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js index a6e198443e810..9ff5662b32b3c 100644 --- a/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js @@ -143,6 +143,8 @@ export function BaseMapsVisualizationProvider(serviceSettings, i18n) { async _updateBaseLayer() { + const DEFAULT_EMS_BASEMAP = 'road_map'; + if (!this._kibanaMap) { return; } @@ -151,13 +153,11 @@ export function BaseMapsVisualizationProvider(serviceSettings, i18n) { if (!this._tmsConfigured()) { try { const tmsServices = await serviceSettings.getTMSServices(); - const firstRoadMapLayer = tmsServices.find((s) => { - return s.id === 'road_map';//first road map layer - }); - const fallback = firstRoadMapLayer ? firstRoadMapLayer : tmsServices[0]; - if (fallback) { - this._setTmsLayer(firstRoadMapLayer); - } + const userConfiguredTmsLayer = tmsServices[0]; + const initBasemapLayer = userConfiguredTmsLayer + ? userConfiguredTmsLayer + : tmsServices.find(s => s.id === DEFAULT_EMS_BASEMAP); + if (initBasemapLayer) { this._setTmsLayer(initBasemapLayer); } } catch (e) { toastNotifications.addWarning(e.message); return;