ArcGIS API For Javascript :如何解决跨网不能正常获取依赖项的问题?

 

一、前言

  政企项目通常会在自组网以及保密网运行,有些单位甚至会有两个物理隔绝的网络存在。通常情况下我们会在两个网络中部署相同的地图服务和依赖项。但是也有其中一个网络密级很高没有服务器资源,不能单独部署依赖项的情况出现。

二、案例与原因初探

  例如:现有 A、B 两张物理隔绝的网络。其中 A 网部署地图服务与依赖项, B 网密级很高,只进不出,且无法部署依赖项。

  我们首先采用的是在前置机 C(双网卡,与 A 双向通信,与 B 单向通信)搭建转发服务,在此过程中就会出现依赖项加载失败的情况。根据对控制台网络请求查看,请求的 js 资源 IP 为 B 网配置项中的 IP 段,说明 A 网中依赖项中的 init.js 和 dojo.js 中配置写死,造成 B 通过 C 无法正常请求到相关资源。

三、解决方案

  核心是使 init.js 和 dojo.js 动态获取主机 IP 更新配置项。基于此思路,我们进行了以下尝试:

  1. 配置项 使用相对路径 —— 失败

  2. 配置项 A 网代理 A 网(使用 ArcGIS 代理 + 原始 IP 端口 拼接路径) —— 失败

  3. 配置项 使用 B 网配置 IP 端口 —— 失败

  4. 配置项  C 机代理 A 网(使用前置机转发 + 原始 IP 端口 拼接路径)——失败

  5. 配置项  C 机代理 B 网(使用前置机转发 + B 网配置 IP 端口 拼接路径)——失败

  6. 配置项 获取当前请求的服务 IP 端口,更新至到配置项 —— 成功 10%

    6.1 遇到的问题及解决思路

    根据自动获取当前服务 IP 端口,在 B 网中可以正常调用 init.js ,但是 zh-cn.js 未能正常加载,说明在加载相关基础 js 时会重新拼接路径,而此时所获取的 baseurl 并非我们在头部修改的当前服务 IP 端口。

    因此需要在源码中找到相对应拼接路径的位置,将其强行修改与头部的 baseurl 保持一致。

    6.2 解决过程

    6.2.1 获取当前服务 IP 端口

(function(exports) {
    var doc = exports.document
      , a = {}
      , expose = +new Date()
      , rExtractUri = /((?:http|https|file):\/\/.*?\/[^:]+)(?::\d+)?:\d+/
      , isLtIE8 = ('' + doc.querySelector).indexOf('[native code]') === -1;
    exports.getCurrAbsPath = function() {
        // FF,Chrome
        if (doc.currentScript) {
            return doc.currentScript.src;
        }
        var stack;
        try {
            a.b();
        } catch (e) {
            stack = e.fileName || e.sourceURL || e.stack || e.stacktrace;
        }
        // IE10
        if (stack) {
            var absPath = rExtractUri.exec(stack)[1];
            if (absPath) {
                return absPath;
            }
        }
        // IE5-9
        for (var scripts = doc.scripts, i = scripts.length - 1, script; script = scripts[i--]; ) {
            if (script.className !== expose && script.readyState === 'interactive') {
                script.className = expose;
                // if less than ie 8, must get abs path by getAttribute(src, 4)
                return isLtIE8 ? script.getAttribute('src', 4) : script.src;
            }
        }
    }();
}(window));

    6.2.2 配置 baseUrl

      将上述代码插入 init.js 最上部分,然后搜索 [HOSTNAME_AND_PATH_TO_JSAPI] ,将其更换为 getCurrAbsPath.replace("/"+getCurrAbsPath.split("/").pop(),"") + "/dojo" 。

    6.2.3 找到二次拼接位置

      根据 zh-cn 检索,找到以下位置。

"*now": function(q) {
    q(['dojo/i18n!*preload*esri/nls/jsapi*["ar","az","ca","cs","da","de-de","el","en-gb","en-us","es-es","fi-fi","fr-fr","he-il","hu","it-it","ja-jp","ko-kr","nl-nl","nb","pl","pt-br","pt-pt","ro","ru","sk","sl","sv","th","tr","zh-tw","zh-cn","ROOT"]'])
},

      在这里打断点,逐行执行,找到拼接处。

Wa = function(a, b, g, d, r, q, h, k, f, x) {
        var t, y, w, m;
        m = /^\./.test(a);
        if (/(^\/)|(\:)|(\.js$)/.test(a) || m && !b)
            return wa(0, a, 0, a);
        a = Va(m ? b.mid + "/../" + a : a);
        if (/^\./.test(a))
            throw c("irrationalPath", a);
        x || m || !q.star || (w = Aa(a, q.star[1]));
        !w && b && (w = (w = Aa(b.mid, q)) && Aa(a, w[1]));
        w && (a = w[1] + a.substring(w[3]));
        b = (na = a.match(/^([^\/]+)(\/(.+))?$/)) ? na[1] : "";
        (t = g[b]) ? a = b + "/" + (y = na[3] || t.main) : b = "";
        var p = 0;
        e(k, function(b) {
            var c = a.match(b[0]);
            c && 0 < c.length && (p = l(b[1]) ? a.replace(b[0], b[1]) : b[1])
        });
        if (p)
            return Wa(p, 0, g, d, r, q, h, k, f);
        if (g = d[a])
            return f ? wa(g.pid, g.mid, g.pack, g.url) : d[a];
        d = (w = Aa(a, h)) ? w[1] + a.substring(w[3]) : b ? ("/" === t.location.slice(-1) ? t.location.slice(0, -1) : t.location) + "/" + y : v("config-tlmSiblingOfDojo") ? "../" + a : a;
        debugger
        /(^\/)|(\:)/.test(d) || (d = r + d);
        console.log(wa(b, a, t, Va(d + ".js")))
        return wa(b, a, t, Va(d + ".js"))
    }

      发现 /(^\/)|(\:)/.test(d) || (d = r + d); 是拼接语句,r 是问题关键。我们只需要在 debugger 处将 r 重新赋值即可。

r=getCurrAbsPath.replace("/" + getCurrAbsPath.split("/").pop(), "") + "/dojo/";

    6.3 测试

      B 网成功地向 C 前置机转发服务请求,获得了 A 网的地图依赖项和地图服务。至此问题解决。

四、总结

  以上就是困扰了很久的跨网未能正常获取地图资源的问题的解决过程与解决方法。

 

posted @ 2019-11-22 12:27  DawudMa  阅读(...)  评论(...编辑  收藏