Skip to content

Support WMTS services that omit the optional ows:OperationsMetadata - #12866

Open
eastagiletracker wants to merge 1 commit into
geosolutions-it:masterfrom
eastagiletracker:agile-board/wmts-optional-operations-metadata
Open

Support WMTS services that omit the optional ows:OperationsMetadata#12866
eastagiletracker wants to merge 1 commit into
geosolutions-it:masterfrom
eastagiletracker:agile-board/wmts-optional-operations-metadata

Conversation

@eastagiletracker

Copy link
Copy Markdown

This PR proposes support for WMTS services that omit the optional ows:OperationsMetadata section, so their layers are listed and can be added from the Catalog instead of the search failing outright (Fixes #6763). We include this PR work along with a full history of your repo at https://eastagiletracker.com/projects/511. You can sign in with your GitHub ID to claim ownership of the project.

What is wrong

getOperations in web/client/utils/WMTSUtils.js dereferences the capabilities document unconditionally:

export const getOperations = (json = {}) => castArray(json.Capabilities["ows:OperationsMetadata"]["ows:Operation"]);

ows:OperationsMetadata is optional in WMTS 1.0.0, and RESTful services routinely leave it out. When it is absent, searchAndPaginate in web/client/api/WMTS.js calls getOperations on its first line and throws, so the promise returned by WMTS.getRecords rejects and the Catalog lists nothing at all for the service.

Both public services named in the two open issues still omit the section today, so the failure is live on current master:

$ curl -s https://tiles.emodnet-bathymetry.eu/wmts/1.0.0/WMTSCapabilities.xml | grep -c OperationsMetadata
0
$ curl -s https://sgx.geodatenzentrum.de/wmts_topplus_open/1.0.0/WMTSCapabilities.xml | grep -c OperationsMetadata
0

Running the five new cases against master (this branch with web/client/utils/WMTSUtils.js reverted) reproduces it exactly at the line issue #6763 points to:

Test correctness of the WMTS APIs
  x GetRecords RESTful without OperationsMetadata
    TypeError: Cannot read properties of undefined (reading 'ows:Operation')
        at getOperations (web/client/utils/WMTSUtils.js)
        at searchAndPaginate (web/client/api/WMTS.js)

What changed

getOperations now reads the optional section defensively and returns an empty array when it is missing, which is enough on its own to stop the throw — getOperation already handles an empty operations array and simply returns undefined, so queryable and GetTileURL come out false and undefined rather than crashing.

getRequestEncoding then has to answer a question the document no longer answers directly. When there are no operations it falls back to the layers, via a new hasTileResourceURL helper: a ResourceURL with resourceType="tile" is exactly what a RESTful service advertises in place of the operations section, so that means RESTful, and anything else keeps the previous KVP default that recordToLayer already documents. This is the first two items of the checklist in issue #4496; the third item there (an explicit KVP/RESTful selector in the catalog UI) is a separate change and is not included here.

Nothing changes for a service that does publish ows:OperationsMetadata: the fallback is only reached when the operations array is empty, so KVP services, RESTful services and the GeoServer 2.15 mixed case all take the same path as before. The existing wmts kvp, wmts rest, GetRecords KVP, GetRecords RESTful and GetRecords KVP for GeoServer 2.15 cases were kept untouched and stay green.

How it was verified

Five cases were added, covering the fix at three levels: WMTSUtils directly (operations parsing, encoding fallback, and a control asserting a document with neither operations nor a tile ResourceURL still resolves to KVP), WMTS.getRecords for the record shape, and api/catalog/WMTS end to end, asserting the layer built from the record carries requestEncoding: 'RESTful' and a usable tile template as its URL. All five fail on master with the TypeError quoted above and pass with the change. The new fixture GetCapabilities-rest-no-operations-metadata.xml follows the anonymised style of the existing WMTS fixtures.

The specs for these two modules and for every other file that imports them — PrintUtils, WMSCacheOptions, the catalog, backgroundselector and layerinfo epics, the leaflet and mapinfo WMTS utils and the OpenLayers Layer spec — were run with karma before and after: 276 passing before, 281 passing after, nothing newly red. eslint on the four touched JS files and prettier --check on the fixture are both clean.

As a last check the same catalog path was pointed at the two real capabilities documents linked above. On master both throw; with the change EMODnet Bathymetry resolves 20 layers and topplus_open resolves 6, each with requestEncoding: 'RESTful' and a tile template that survives into the layer:

[emodnet]  matched=20 encoding=RESTful name=baselayer url=https://tiles.emodnet-bathymetry.eu/2020/baselayer/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png
[topplus]  matched=6  encoding=RESTful name=web       url=https://sgx.geodatenzentrum.de/wmts_topplus_open/tile/1.0.0/web/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.png

How this was managed

This work was tracked as a single story, WMTS catalog fails if OperationMetadata is missing, but it is optional, on a board imported from this repository's own issues, pull requests and milestones — the same board linked at the top: https://eastagiletracker.com/projects/511

board

If you'd rather not receive contributions like this, reply no-more-prs on this pull request and we won't open any further ones on your repositories.


Lawrence W. Sinclair
CEO / East Agile
linkedin.com/in/lwsinclair/
eastagile.com

getOperations dereferenced Capabilities["ows:OperationsMetadata"]["ows:Operation"]
unconditionally, so a WMTS GetCapabilities document without that optional section
made the catalog search throw a TypeError and list no layers at all.

getOperations now returns an empty array when the section is absent, and
getRequestEncoding falls back to RESTful when the layers declare a tile
ResourceURL, keeping the previous KVP default otherwise.
@cla-bot

cla-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown

In order to contribute to the MapStore project, the CLA (Contributor License agreement) should be sent signed to GeoSolutions. Please consult contributing rules at: https://github.com/geosolutions-it/MapStore2/wiki/Contributing-to-MapStore#contributing-code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WMTS catalog fails if OperationMetadata is missing, but it is optional

1 participant