2

We have arcgis js api application (v 3.18) with TOC UI where users can turn individual layers on and off.

We have an issue with this WMS service. When users start turning on/off layers, WMSLayer sends a list of layers to WMS in URL parameter LAYERS=... The string with visible layers becomes too long and our app stops working on IE which has 2048 chars in URL limit, if I remember correctly. It still works on Chrome (it can handle longer URLs).

Is there a way to instruct WMSLayer to go switch to POST if URL is too long? Do we need to have a proxy to handle POSTs as support for POST is not mandatory for WMS server? OR better is it possible to change URL to shorter one of GetMap GET requests and handle request on proxy communicating to real WMS using long URL?

Here is the example of failing REQUEST=GetMap URL. URL length is 2541. Chrome and Firefox open it normally: you see requested image. IE 11 truncates URL to 2048 chars, Edge truncates it to 2084 chars (strange number, maybe some Edge developer mistype the constant). So the shortened URL becomes invalid and you get error in IE and Edge.

Attempts to hook XHR communications with either

esriRequest.setRequestPreCallback(this.esriRequestPreCallback.bind(this));

or even brute force:

this.dojoXHR = dojo.xhr;
dojo.xhr = function (method, options) {
    console.log(method, options.url);
    return this.dojoXHR.apply(this.dojoXHR, arguments);
}.bind(this);

don't work. WMSLayer loads image needed by assigning URL to HTML Image element, i.e. image.src=url. These GETs don't go via XHR. I doubt if it's possible to hook to image.src setter.

Another approach to shorten URL is specification of GetMap params LAYERS. OpenGIS spec simply tells "The value of the LAYERS parameter is a comma-separated list of one or more valid layer names". ArcGIS WMS allows 2 forms: "Comma-separated list of one or more map layers (for example, 0,1,2 or layer1,layer2)." It's not clear how layer order is made, but this could help to communicate with this particular WMS which is running on ArcGIS. This GetMap request, for example uses short LAYERS form and it works.

1

I found a way how to hook and change URLs of WMS layer images. Real implementation will require much more work (proxy, making sure both client and proxy has the same dictionary layer name - id), but here is proof of concept. It uses private method _imgSrcFunc of WMSLayer, so may not necessary work on all ArcGIS jsapi versions.

var base_WMSLayer_imgSrcFunc = WMSLayer.prototype._imgSrcFunc,
    isIE = navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0;

WMSLayer.prototype._imgSrcFunc = function (url) {
    var urlParts, fixedUrlParts = [];
    if (url.startsWith(myWmsUrlRoot) && 
        encodeURI(url).length > 2048) {
        urlParts = urlUtils.urlToObject(url);
        if (urlParts.query && urlParts.query.LAYERS) {
            fixedUrlParts.push(urlParts.path);
            fixedUrlParts.push('?');
            _.each(_.pairs(urlParts.query), function (kv) {
                var key = kv[0], value = kv[1];
                if (key === 'LAYERS') {
                    // ArcGIS WMS specific: can compress layer names to layer ids;
                    // real implementation will take them from this (WMSLayer) if it's ArcGIS server
                    // and redirect to special proxy that will "unpack" real layer names from numbers
                    // and make a call to true WMS...
                    value = '0,1,2,3,4,5,6,7,8,9,10';
                }

                fixedUrlParts.push(key);
                fixedUrlParts.push('=');
                fixedUrlParts.push(value);
                fixedUrlParts.push('&');
            });

            // change url to one with adjusted LAYERS param
            url = fixedUrlParts.join('');
        }
    }

    // IE fails on national chars in layer names, fix it
    if (isIE) {
        url = encodeURI(url);
    }

    base_WMSLayer_imgSrcFunc.apply(this, [url]);
};
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.