terriajs icon indicating copy to clipboard operation
terriajs copied to clipboard

JSON encoded parameters triggers malformed WMS getMap tiles requests

Open alessioarena opened this issue 1 year ago • 5 comments

I have the need of using JSON encoded parameters in my WMS server, and I've been testing this against TerriaJS deployed as NationalMap.

The parameter I need to pass is a simple JSON encoded dictionary, for example (simple colormap):

{"-1.0":"#000000","-0.2":"#a50026","0":"#d73027","0.1":"#f46d43","0.2":"#fdae61","0.3":"#fee08b","0.4":"#ffffbf","0.5":"#d9ef8b","0.6":"#a6d96a","0.7":"#66bd63","0.8":"#1a9850","0.9":"#006837","1.0":"#006837"}

If I test this against my WMS server, for example by requesting GetCapabilities, the URL is generated like this:

http://127.0.0.1:8000/cog/wms?unscale=false&resampling=nearest&rescale=0%2C100000&colormap=%5B%7B%22-1.0%22%3A%22%23000000%22%2C%22-0.2%22%3A%22%23a50026%22%2C%220%22%3A%22%23d73027%22%2C%220.1%22%3A%22%23f46d43%22%2C%220.2%22%3A%22%23fdae61%22%2C%220.3%22%3A%22%23fee08b%22%2C%220.4%22%3A%22%23ffffbf%22%2C%220.5%22%3A%22%23d9ef8b%22%2C%220.6%22%3A%22%23a6d96a%22%2C%220.7%22%3A%22%2366bd63%22%2C%220.8%22%3A%22%231a9850%22%2C%220.9%22%3A%22%23006837%22%2C%221.0%22%3A%22%23006837%22%7D%5D&colormap_type=interval&REQUEST=GetCapabilities&SERVICE=wms&VERSION=1.3.0&LAYERS=mylayer&TRANSPARENT=false

This is successful, as well as any other request I make like GetMap and GetLegendGraphic.

I then moved to testing this using NationalMap, in particular by adding a WMS url. Adding the layer is again successful, however the tiles GetMap requests from NationalMap end up being malformed, for example:

http://127.0.0.1:8000/cog/wms?transparent=true&format=image%2Fpng&exceptions=XML&styles=default&version=1.3.0&unscale=false&resampling=nearest&rescale=0%2C100000&colormap=%7B%22-1.0%22%3A%22%23000000%22%2C%22-0.2%22%3A%22%23a50026%22%2C%220%22%3A%22%23d73027%22%2C%220.1%22%3A%22%23f46d43%22%2C%220.2%22%3A%22%23fdae61%22%2C%220.3%22%3A%22%23fee08b%22%2C%220.4%22%3A%22%23ffffbf%22%2C%220.5%22%3A%22%23d9ef8b%22%2C%220.6%22%3A%22%23a6d96a%22%2C%220.7%22%3A%22%2366bd63%22%2C%220.8%22%3A%22%231a9850%22%2C%220.9%22%3A%22%23006837%22%2C%221.0%22%3A%22%23006837%22%7D&colormap_type=interval&TRANSPARENT=false&service=WMS&request=GetMap&layers=mylayer&bbox=%7BsouthProjected%7D%2C%7BwestProjected%7D%2C%7BnorthProjected%7D%2C%7BeastProjected%7D&width=%7Bwidth%7D&height=%7Bheight%7D&crs=EPSG%3A4326

If you focus on the bbox, width and height that are requested by TerriaJS, those are the literal values:

bbox={southProjected},{westProjected},{northProjected},{eastProjected}&width={width}&height={height}

The problem disappears if I remove the JSON encoded dictionary, or if I convert it to a list of lists.

It seems that the presence of { and } associated with the dictionary may interfere with the generation of the URL (probably because you are using a templated URL that interpret them as fields?)

alessioarena avatar Sep 14 '23 04:09 alessioarena

Further digging into it, it seems that incoming parameters to TerriaJS are correctly encoded to avoid special characters conflicts (e.g. {, } and #), however the same parameters are not re-encoded when sent from TerriaJS to the WMS service.

I have been having similar issues using a list of lists approach, but containing hex color codes (using the special character #)

alessioarena avatar Sep 21 '23 04:09 alessioarena

Hi @alessioarena

Have you tried using the parameters trait?

Additional parameters to pass WMS GetMap and GetFeatureInfo requests. Style parameters are stored as CSV in styles, dimension parameters are stored in dimensions.

For example

{
      "name": "WMS with parameters",
      "type": "wms",
      "url": "https://example.com/wms",
      "layers": "layer_name",
      "parameters": {
        "colormap": "%5B%7B%22-1.0%22%3A%22%23000000%22%2C%22-0.2%22%3A%22%23a50026%22%2C%220%22%3A%22%23d73027%22%2C%220.1%22%3A%22%23f46d43%22%2C%220.2%22%3A%22%23fdae61%22%2C%220.3%22%3A%22%23fee08b%22%2C%220.4%22%3A%22%23ffffbf%22%2C%220.5%22%3A%22%23d9ef8b%22%2C%220.6%22%3A%22%23a6d96a%22%2C%220.7%22%3A%22%2366bd63%22%2C%220.8%22%3A%22%231a9850%22%2C%220.9%22%3A%22%23006837%22%2C%221.0%22%3A%22%23006837%22%7D%5D",
        "unscale": "false",
        "resampling": "nearest",
        "rescale": "0%2C100000",
        "colormap_type": "interval"
      }
    }

Unfortunately this won't work when you add URLs to maps.

As for why the URL template isn't working correctly with those extra parameters, I'm not sure, I believe this is handled by cesium.

In Terria, we just remove "problematic" parameters and then pass the URL to Cesium's WebMapServiceImageryProvider

https://github.com/TerriaJS/terriajs/blob/53c6ecacb6df515c91ced9dd64fb6a64a9d089c1/lib/Models/Catalog/Ows/WebMapServiceCatalogItem.ts#L533-L548

nf-s avatar Oct 04 '23 09:10 nf-s

Thanks @nf-s, unfortunately we are forced to use the URL option, but you have me something to look at for troubleshooting.

Are the individual tiles GetMap requests handled by WebMapServiceImageProvider ? If that is the case is definitely a Cesium problem and I'll raise it with them.

alessioarena avatar Oct 04 '23 09:10 alessioarena

I just tried to recreate the example in Cesium - but it is definitely passing the parameters correctly through to GetMap requests

That example is using the latest version of cesium, but we are currently using an older version - so it is possible that this has already been fixed by them.

nf-s avatar Oct 04 '23 10:10 nf-s

Sorry I forgot to answer your question! Yes Cesium handles all GetMap and GetFeatureInfo requests

nf-s avatar Oct 04 '23 10:10 nf-s