1

設定:

リモート測定ステーションがあり、集中収集/処理/提示サーバー (Web サーバーを使用) があり、収集されたデータを顧客に表示する観測ステーションがあります。

これらの観測ステーションは、中央サーバーからそれぞれ 1 つの特定の Web ページを表示するキオスク モードで動作する Web ブラウザーを備えた、最低限の単純な組み込みコンピューターで構成されています。この Web ページは、特定の測定ステーションの最新の測定値を表示する AJAX で更新されます。固定モニターに接続されたこれらのステーションは、何年もほとんどメンテナンスフリーで稼働するはずです。

これでほとんどの問題は解決しましたが、問題は次のとおりです。Web サーバーに障害が発生した場合はどうなるでしょうか。ブラウザは、「到達不能」、「404」、「許可が拒否されました」、「500」、またはその時点でサーバーが取ったあらゆるモードの障害を読み込み、誰かが観測ステーションを手動で再起動するまでそこにとどまります。

私が思いついた一般的な解決策は、ブラウザーのホームページを監視対象のページではなく、常に利用可能なローカル HTML ファイルに設定することです。このファイルは、リモート ページが読み込まれて正しく更新されているかどうかを定期的にチェックし、失敗した場合は再読み込みします。何らかの理由で実行する。

問題:

問題はクロスフレームスクリプティングにあります。ターゲットWebページは、フレーム、iframe、テキスト/HTMLタイプのオブジェクト、またはローカルの「コンテナ」ファイルを削除/無効にせずに表示する他の方法としてロードする必要があると思います. 数年前にクロス フレーム スクリプティング ページを作成しましたが、セキュリティ対策を回避するのは簡単ではありませんでした。それ以来、セキュリティは強化されたに違いありません。

そのため、リモート サーバーからロードされたページには、すべてがうまくいった場合は定期的に (setInterval で) 起動される JavaScript が含まれており、何かが壊れている場合は起動されません。このシグナルがコンテナ フレームに定期的に到着すると、タイムアウトがリセットされ、他のアクションは実行されなくなります。

シグナルが届かない場合は、タイムアウトの期限が切れると、サーバーが修正されて適切なコンテンツがロードされるまで、コンテナーはロードされた Web ページの定期的な更新を開始し、そのことをローダーに通知します。

特定の関数がトリガーされるたびに、リモート ページが file:// URL からロードされたローカル (コンテナー) ページに "生きている" (たとえば、変数を設定する) ことを知らせるにはどうすればよいですか?

4

2 に答える 2

2

portholeと呼ばれるライブラリがあり、これは基本的に SF. の回答で説明されていることを行いますが、より正式な形式です。2 つの iframe のうちの 1 つを表示するように切り替える Web ページを作成しました。私が持っているトップレベルのWebページで

var windowProxy;
windowProxy = new Porthole.WindowProxy(baseURL + '/porthole/proxy.html', frameId);
windowProxy.addEventListener(onMessage);
...
function onMessage(messageEvent) {
    if (messageEvent.origin !== baseURL) {
        $log.error(logPrefix + ': onMessage: invalid origin');
        console.dir(messageEvent);
        return;
    }
    if (messageEvent.data.pong) {
        pongReceived();
        return;
    }
    $log.log(logPrefix + ': onMessage: unknown message');
    console.dir(messageEvent);
}
...
var sendPing = function () {
    $log.log(logPrefix + ': ping to ' + baseURL);
    ...
    windowProxy.post({ 'ping': true });
};

加えて、いくつかの追加の制御ロジック。子 Web ページでは、以下を追加する必要がありました (さらにportholeService.init()、コントローラーからの呼び出し)。

// This service takes care of porthole (https://github.com/ternarylabs/porthole)
// communication if this is invoked from a parent frame having this web page
// as a child iframe. Usage of porthole is completely optional, and should
// have no impact on anything outside this service. The purpose of this
// service is to enable some failover service to be build on top of this
// using two iframes to switch between.
services.factory('portholeService', ['$rootScope', '$log', '$location', function ($rootScope, $log, $location) {
    $log.log('Hello from portholeService');

    function betterOffWithFailover() {
        ...
    }

    function onMessage(messageEvent) {
        $rootScope.$apply(function () {
            if (messageEvent.origin !== baseUrl) {
                $log.error('onMessage: invalid origin');
                console.dir(messageEvent);
                return;
            }

            if (!messageEvent.data.ping) {
                $log.error('unknown message');
                console.dir(messageEvent.data);
                return;
            }

            if (betterOffWithFailover()) {
                $log.log('not sending pong');
                return;
            }

            windowProxy.post({ 'pong': true });
        });
    }

    var windowProxy;
    var baseUrl;
    function init() {
        baseUrl = $location.protocol() + '://' + $location.host() + ':' + $location.port();
        windowProxy = new Porthole.WindowProxy(baseUrl + '/porthole/proxy.html');
        windowProxy.addEventListener(onMessage);
    }

    return {
        init: init
    };
}]);

参考までに、これらのページはAngularJSを使用$rootScope.$applyしています。

于 2014-10-09T17:39:32.403 に答える
0

クロスフレーム、クロスサイト通信の方法は、postMessage を使用します。

含まれているフレームは、正しい実行ごとに次のように実行する必要があります。

window.top.postMessage('tyrp', '*');

コンテナ ドキュメントには、次のものが含まれている必要があります。

window.onmessage = function(e)
{
    if (e.data == 'tyrp') {
        //reset timeout here
    }
};
于 2013-04-16T13:54:18.397 に答える