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: 21 additions & 0 deletions web/client/api/__tests__/WMTS-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import expect from 'expect';

import API, { getLayerTileMatrixSetsInfo, parseUrl } from '../WMTS';
import { getGetTileURL } from '../../utils/WMTSUtils';
import { castArray } from 'lodash';
import MockAdapter from 'axios-mock-adapter';
import axios from '../../libs/ajax';
let mockAxios;
Expand Down Expand Up @@ -58,6 +59,26 @@ describe('Test correctness of the WMTS APIs', () => {
}
});
});
it('GetRecords RESTful without OperationsMetadata', (done) => {
API.getRecords('base/web/client/test-resources/wmts/GetCapabilities-rest-no-operations-metadata.xml', 0, 2, '').then((result) => {
try {
expect(result).toExist();
expect(result.numberOfRecordsMatched).toBe(2);
result.records.map(record => {
expect(record.requestEncoding).toBe('RESTful');
expect(record.queryable).toBe(false);
expect(record.GetTileURL).toNotExist();
expect(getGetTileURL(record)).toEqual(castArray(record.ResourceURL).map(({ $: v }) => v.template));
});
expect(result.records[0].style).toBe("default");
expect(result.records[0].format).toBe("image/png");
expect(getGetTileURL(result.records[0])).toEqual(["https://maps.sampleServer.org/basemap/baselayer/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png"]);
done();
} catch (ex) {
done(ex);
}
}).catch(done);
});
it('GetRecords KVP for GeoServer 2.15', (done) => {
// GS 2.15 has ResourceURLs together with KVP. This checks that the proper URL is returned by getTileURL, used to generate the layer. See #3796
API.getRecords('base/web/client/test-resources/wmts/GetCapabilities-1.0.0_gs_2.15.xml', 0, 3, '').then((result) => {
Expand Down
19 changes: 18 additions & 1 deletion web/client/api/catalog/__tests__/WMTS-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import expect from 'expect';

import { getCatalogRecords } from '../WMTS';
import { getCatalogRecords, getLayerFromRecord, textSearch } from '../WMTS';

describe('Test correctness of the WMTS APIs', () => {
it('wmts', () => {
Expand Down Expand Up @@ -142,6 +142,23 @@ describe('Test correctness of the WMTS APIs', () => {
expect(records.length).toBe(1);
expect(records[0].references[0].url).toBe(undefined);
});
it('wmts layer from a RESTful service without OperationsMetadata', (done) => {
textSearch('base/web/client/test-resources/wmts/GetCapabilities-rest-no-operations-metadata.xml', 1, 2, '').then((result) => {
try {
const records = getCatalogRecords(result, {});
expect(records.length).toBe(2);
expect(records[0].requestEncoding).toBe('RESTful');
const layer = getLayerFromRecord(records[0]);
expect(layer.type).toBe('wmts');
expect(layer.name).toBe('baselayer');
expect(layer.requestEncoding).toBe('RESTful');
expect(layer.url).toBe('https://maps.sampleServer.org/basemap/baselayer/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png');
done();
} catch (ex) {
done(ex);
}
}).catch(done);
});
it('wmts capabilities url', () => {
const wmtsRecords = [{ GetTileURL: "tileURL" }];
const records = getCatalogRecords({ records: wmtsRecords });
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<Capabilities xmlns="http://www.opengis.net/wmts/1.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd" version="1.0.0">
<ows:ServiceIdentification>
<ows:Title>sample server without operations metadata</ows:Title>
<ows:Abstract>RESTful WMTS that omits the optional ows:OperationsMetadata section</ows:Abstract>
<ows:ServiceType>OGC WMTS</ows:ServiceType>
<ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>
<ows:Fees>none</ows:Fees>
<ows:AccessConstraints>none</ows:AccessConstraints>
</ows:ServiceIdentification>
<ows:ServiceProvider>
<ows:ProviderName>City of Nowhere</ows:ProviderName>
<ows:ProviderSite xlink:href="https://www.sampleServer.org"/>
</ows:ServiceProvider>
<Contents>
<Layer>
<ows:Title>Base Layer</ows:Title>
<ows:Abstract>Base layer of the sample server</ows:Abstract>
<ows:WGS84BoundingBox crs="urn:ogc:def:crs:OGC:2:84">
<ows:LowerCorner>-180.0 -90.0</ows:LowerCorner>
<ows:UpperCorner>180.0 90.0</ows:UpperCorner>
</ows:WGS84BoundingBox>
<ows:Identifier>baselayer</ows:Identifier>
<Style isDefault="true">
<ows:Identifier>default</ows:Identifier>
</Style>
<Format>image/png</Format>
<TileMatrixSetLink>
<TileMatrixSet>google3857</TileMatrixSet>
</TileMatrixSetLink>
<ResourceURL format="image/png" template="https://maps.sampleServer.org/basemap/baselayer/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png" resourceType="tile"/>
</Layer>
<Layer>
<ows:Title>Overlay Layer</ows:Title>
<ows:Abstract>Overlay layer of the sample server</ows:Abstract>
<ows:WGS84BoundingBox crs="urn:ogc:def:crs:OGC:2:84">
<ows:LowerCorner>-180.0 -90.0</ows:LowerCorner>
<ows:UpperCorner>180.0 90.0</ows:UpperCorner>
</ows:WGS84BoundingBox>
<ows:Identifier>overlaylayer</ows:Identifier>
<Style isDefault="true">
<ows:Identifier>default</ows:Identifier>
</Style>
<Format>image/png</Format>
<TileMatrixSetLink>
<TileMatrixSet>google3857</TileMatrixSet>
</TileMatrixSetLink>
<ResourceURL format="image/png" template="https://maps.sampleServer.org/basemap/overlaylayer/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png" resourceType="tile"/>
</Layer>
<TileMatrixSet>
<ows:Identifier>google3857</ows:Identifier>
<ows:SupportedCRS>urn:ogc:def:crs:EPSG:6.18.3:3857</ows:SupportedCRS>
<TileMatrix>
<ows:Identifier>0</ows:Identifier>
<ScaleDenominator>559082264.029</ScaleDenominator>
<TopLeftCorner>-20037508.3428 20037508.3428</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>1</MatrixWidth>
<MatrixHeight>1</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>1</ows:Identifier>
<ScaleDenominator>279541132.014</ScaleDenominator>
<TopLeftCorner>-20037508.3428 20037508.3428</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>2</MatrixWidth>
<MatrixHeight>2</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>2</ows:Identifier>
<ScaleDenominator>139770566.007</ScaleDenominator>
<TopLeftCorner>-20037508.3428 20037508.3428</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>4</MatrixWidth>
<MatrixHeight>4</MatrixHeight>
</TileMatrix>
</TileMatrixSet>
</Contents>
<ServiceMetadataURL xlink:href="https://maps.sampleServer.org/basemap/1.0.0/WMTSCapabilities.xml"/>
</Capabilities>
22 changes: 20 additions & 2 deletions web/client/utils/WMTSUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,26 @@ export const getTileMatrixSet = (tileMatrixSet, srs, allowedSRS, matrixIds = {},
*/
export const getRequestEncoding = json => {
const operations = WMTSUtils.getOperations(json);
if (operations.length === 0) {
// ows:OperationsMetadata is optional, so the encoding can only be deduced
// from the layers: a tile ResourceURL is what a RESTful service advertises
return WMTSUtils.hasTileResourceURL(json) ? "RESTful" : "KVP";
}
return WMTSUtils.getOperation(operations, "GetTile", "KVP") ? "KVP" : WMTSUtils.getOperation(operations, "GetTile", "RESTful") && "RESTful";
};
export const getOperations = (json = {}) => castArray(json.Capabilities["ows:OperationsMetadata"]["ows:Operation"]);
/**
* Gets the 'Operations' array from the WMTS Capabilities json parsed object.
* Returns an empty array when the optional 'ows:OperationsMetadata' section is missing
*/
export const getOperations = (json = {}) => {
const operations = json?.Capabilities?.["ows:OperationsMetadata"]?.["ows:Operation"];
return operations ? castArray(operations) : [];
};
/**
* Checks if at least one layer of the WMTS Capabilities json parsed object declares a tile ResourceURL
*/
export const hasTileResourceURL = (json = {}) => castArray(json?.Capabilities?.Contents?.Layer || [])
.some((layer) => castArray(layer.ResourceURL || []).some((resource) => resource?.$?.resourceType === "tile"));
/**
* gets the first operation of the type and with the name provided from the 'Operations' array of the WMTS Capabilities json parsed object
*/
Expand Down Expand Up @@ -213,5 +230,6 @@ export const generateGeoServerWMTSUrl = (options) => {

WMTSUtils = {
getOperations,
getOperation
getOperation,
hasTileResourceURL
};
22 changes: 22 additions & 0 deletions web/client/utils/__tests__/WMTSUtils-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import xml2js from 'xml2js';
import * as WMTSUtils from '../WMTSUtils';
import restCapabilities from 'raw-loader!../../test-resources/wmts/GetCapabilities-rest.xml';
import kvpCapabilities from 'raw-loader!../../test-resources/wmts/GetCapabilities-1.0.0.xml';
import restCapabilitiesNoOperationsMetadata from 'raw-loader!../../test-resources/wmts/GetCapabilities-rest-no-operations-metadata.xml';

describe('Test the WMTSUtils', () => {
it('get matrix ids with object', () => {
Expand Down Expand Up @@ -54,6 +55,27 @@ describe('Test the WMTSUtils', () => {
done();
});
});
it('wmts rest without OperationsMetadata', (done) => {
xml2js.parseString(restCapabilitiesNoOperationsMetadata, { explicitArray: false }, (ignore, json) => {
const operations = WMTSUtils.getOperations(json);
expect(operations).toEqual([]);
expect(WMTSUtils.getOperation(operations, "GetTile", "KVP")).toNotExist();
expect(WMTSUtils.getOperation(operations, "GetTile", "RESTful")).toNotExist();
// OperationsMetadata is optional, the RESTful encoding is advertised by the tile ResourceURL
expect(WMTSUtils.getRequestEncoding(json)).toBe("RESTful");
const tileURLs = WMTSUtils.getGetTileURL({ ...json.Capabilities.Contents.Layer[0], requestEncoding: "RESTful" });
expect(tileURLs).toEqual(["https://maps.sampleServer.org/basemap/baselayer/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png"]);
done();
});
});
it('getOperations with empty capabilities', () => {
expect(WMTSUtils.getOperations()).toEqual([]);
expect(WMTSUtils.getOperations({})).toEqual([]);
expect(WMTSUtils.getOperations({ Capabilities: {} })).toEqual([]);
});
it('getRequestEncoding without OperationsMetadata and without tile ResourceURL', () => {
expect(WMTSUtils.getRequestEncoding({ Capabilities: { Contents: { Layer: { "ows:Identifier": "layer" } } } })).toBe("KVP");
});
it('parseTileMatrixSetOption', () => {
const layer = WMTSUtils.parseTileMatrixSetOption({
availableTileMatrixSets: {
Expand Down