geosolutions-it / MapStore2

The solution to create and share maps, dashboards, geostories with 3D support on the web. And it is open-source too!
https://mapstore.geosolutionsgroup.com/
Other
510 stars 398 forks source link

[interoperability] WMS GetMap queries for elevation layer lack the mandatory STYLES parameter #8599

Open landryb opened 2 years ago

landryb commented 2 years ago

Description

using our own DEM service on mapserver to serve BIL data for elevation (cf #6579), so far it works fine.

we're in the process of upgrading mapserver to 8.0 and now (cf MapServer/MapServer#6012) by default it enforces the (already required by the WMS specification ?) STYLES parameter, which isnt sent by mapstore 2021.02.

sample query sent by mapstore: /mnt?SERVICE=WMS&REQUEST=GetMap&layers=mnt_raw&version=1.3.0&bbox=4.2173767089843865,43.240814208984375,4.395904 541015629,43.419342041015625&crs=CRS:84&srs=CRS:84&format=image/bil&width=65&height=65

after a quick look at the code in 2021.02, there was https://github.com/geosolutions-it/MapStore2/blob/2022.01.xx/web/client/utils/cesium/BILTerrainProvider.js#L563 which could have been modified to send an empty &styles=, but it was removed/lost in 68ef69186a - now i think the right place to add the missing param should be https://github.com/geosolutions-it/MapStore2/blob/master/web/client/utils/cesium/GeoServerBILTerrainProvider.js#L207 - @allyoucanmap does this make sense to you ?

Expected Result

mapstore should send the mandatory STYLES parameter

Current Result

mapserver returns

msWMSLoadGetMapParams(): WMS server error. Missing required parameter STYLES.
Note to service administrators: defining the "wms_allow_getmap_without_styles" "true" MAP.WEB.METADATA item will disable this check
(backward compatibility with behaviour of MapServer < 8.0)

Other useful information

interoperability is hard.

nmtoken commented 1 year ago

An empty styles parameter is styles& not &styles= see Table 2 — Structure of WMS request using HTTP GET in the standard https://portal.ogc.org/files/?artifact_id=14416

landryb commented 1 year ago

as seen in testing #9054, the issue is also seen for GetFeatureInfo requests. Per MapServer/MapServer#6812 STYLES is a mandatory parameter for GetMap and GetFeatureInfo.

Digging in the code, and doing step-by-step debugging in the js, i'm puzzled because styles is set here (even if undefined) https://github.com/geosolutions-it/MapStore2/blob/master/web/client/utils/mapinfo/wms.js#L66 and from my understanding of the call stack, the attribute is still present in the object passed to the caller. But the end request lacks it:

http://localhost:8081/proxy/?url=https://demo.mapserver.org/cgi-bin/wms?service=WMS&version=1.1.1&request=GetFeatureInfo&exceptions=application%2Fjson&id=continents__88a5da60-cd4d-11ed-b7a7-6d0f03fc7c4a&layers=continents&query_layers=continents&x=51&y=51&height=101&width=101&srs=EPSG%3A3857&bbox=-997961.8412912617%2C4226661.916057111%2C2954749.7653917726%2C8179373.522740145&feature_count=10&info_format=text%2Fplain&ENV=mapstore_language%3Aen

can there be something pruning undefined params from the struct before sending the XHR query ? The behaviour is the same if the target server is added to useCORS and the mapstore proxy isnt used to send the GFI request.

nmtoken commented 1 year ago

STYLES isn't mandatory for WMS that support SLD. For SLD enabled WMS, both layers and styles can be omitted if the GetMap or GetFeatureInfo request include either an SLD or sld_BODY parameter.

| Request Parameter | Required/Optional | Description | | LAYERS=layer_list | R | Comma-separated list of one or more map layers. Optional if SLD parameter is present. | | STYLES=style_list | R | Comma-separated list of one rendering style per requested layer. Optional if SLD parameter is present. |

landryb commented 1 year ago

fwiw, even if i'm not using mapserver anymode as a 3d terrain source on my production instance i've found out that by defining an empty styles parameter in the additionalLayers array in localConfig.json that forced mapstore to send the missing param to the remote server, at least for queries initiated by MousePosition plugin.

              "additionalLayers": [{
                "type": "wms",
                "url": "https://wms.dev.craig.fr/mnt",
                "visibility": true,
                "title": "Elevation",
                "name": "mnt_raw",
------->        "styles": "",
                "format": "image/bil",
                "useForElevation": true,
                "nodata": -9999,
                "littleendian": true,
                "hidden": true
              }],

and with that no need for "wms_allow_getmap_without_styles" "true" on the mapserver config side.

I've tried fixing it in the code with:

index 48ad8595e..56ce6f0c8 100644
--- a/web/client/utils/cesium/GeoServerBILTerrainProvider.js
+++ b/web/client/utils/cesium/GeoServerBILTerrainProvider.js
@@ -207,6 +207,7 @@ function getMetadataDescription(options) {
         let urlTemplate = url + '?SERVICE=WMS&REQUEST=GetMap' +
             '&layers=' + layerName +
             '&version=' + version +
+            '&styles=' +
             '&bbox=';

         if (isNewVersion && firstAxeIsLatitude) {

but i'm not able to make cesium issue requests for the elevation layer when going to 3d mode, and from my understanding MousePosition plugin uses different codepaths to make WMS requests to the server to get its elevation info.

landryb commented 1 year ago

cesium fails to send requests for the elevation layer because it needs to be told the terrainProvider is of type wms, but that's not enough, something fails badly as (in my understanding) a regression from 68ef69186a.

when iterating over the layers of https://wms.craig.fr/mnt?service=wms&request=getcapabilities in https://github.com/geosolutions-it/MapStore2/blob/master/web/client/utils/cesium/GeoServerBILTerrainProvider.js#L265, for some reason isWorkSpaceCapabilities is true (while no layer name have :) so no layer matches and boom:

Uncaught (in promise) TypeError: layerNode is undefined
    fromWSMCapabilitiesToOptions webpack://mapstore2/./web/client/utils/cesium/GeoServerBILTerrainProvider.js?:231
    parseOptions webpack://mapstore2/./web/client/utils/cesium/GeoServerBILTerrainProvider.js?:266

the isWorkSpaceCapabilities boolean comes from https://github.com/geosolutions-it/MapStore2/blob/master/web/client/utils/cesium/GeoServerBILTerrainProvider.js#L305 and something might be wrong there. @allyoucanmap ?

if i force-set isWorkSpaceCapabilities to false, and with landryb/Mapstore2@487e398 i have proper BIL requests with the empty style parameter hitting my dev mapserver instance (without needing the empty style parameter in the additionalLayers config).