ブラウザが異なるオリジンでホストされている JavaScript ファイルからのエラーをキャッチすると、そのエラーの詳細を一般的な "Script error." メッセージに置き換えます。これは、同一オリジンポリシーによって定義されたブラウザのセキュリティ機能です。エラーメッセージ、ソース URL、行番号がすべて削除されるため、これらのエラーは ARMS ブラウザ監視で診断することが困難です。
このトピックでは、「Script error.」が発生する理由と、2つの修正方法(CORS の有効化 (推奨) と try...catch での呼び出しのラップ)について説明します。最後のセクションでは、ARMS SDK でスクリプトエラーが対処不要な場合にフィルタリングする方法について説明します。
ブラウザがクロスオリジンのエラー詳細を非表示にする理由
ブラウザはエラーレポートに 同一オリジンポリシー を適用します。http://test.com のページが http://another-domain.com/app.js からスクリプトをロードする場合、ブラウザは詳細なエラー情報がページの window.onerror ハンドラに到達するのをブロックします。これにより、サードパーティスクリプトがエラーメッセージを介して機密データを漏洩するのを防ぎます。
例: ページが未定義の関数を呼び出すクロスオリジンスクリプトをロードします。
<!doctype html>
<html>
<head>
<title>Test page in http://test.com</title>
</head>
<body>
<script src="http://another-domain.com/app.js"></script>
<script>
window.onerror = function (message, url, line, column, error) {
console.log(message, url, line, column, error);
}
foo(); // app.js で定義されている foo() を呼び出します
</script>
</body>
</html>// another-domain.com/app.js
function foo() {
bar(); // ReferenceError: bar は関数ではありません
}実際の ReferenceError の代わりに、window.onerror ハンドラは以下を受け取ります。
"Script error.", "", 0, 0, undefined内部的に、ブラウザはエラーをページに渡す前にサニタイズします。
bool ScriptExecutionContext::sanitizeScriptError(String& errorMessage, int& lineNumber, String& sourceURL)
{
KURL targetURL = completeURL(sourceURL);
if (securityOrigin()->canRequest(targetURL))
return false;
errorMessage = "Script error.";
sourceURL = String();
lineNumber = 0;
return true;
}最も一般的な原因は、CDN で JavaScript をホストすることです。CDN ドメインがご利用のページのドメインと異なるため、これらのスクリプトからのすべてのエラーは "Script error." として表示されます。
ソリューション 1: CORS の有効化 (推奨)
クロスオリジンスクリプトから完全なエラー詳細を取得するには、HTML のスクリプトタグと、スクリプトをホストするサーバーのレスポンスヘッダーの両方を構成します。
ステップ 1: スクリプトタグに crossorigin 属性を追加
<script src="http://another-domain.com/app.js" crossorigin="anonymous"></script>crossorigin="anonymous" 属性は、認証情報 (クッキーまたはクライアント証明書) をサードパーティサーバーに送信せずにスクリプトをフェッチするようにブラウザに指示します。
ステップ 2: サーバーに CORS レスポンスヘッダーを追加
スクリプトをホストするサーバーは、Access-Control-Allow-Origin ヘッダーを返す必要があります。すべてのオリジンを許可するには:
Access-Control-Allow-Origin: *ご利用のドメインへのアクセスを制限するには:
Access-Control-Allow-Origin: http://test.comほとんどの CDN プロバイダーは、デフォルトで Access-Control-Allow-Origin ヘッダーをすでに含んでいます。検証するには、以下を実行します。
curl --head https://retcode.alicdn.com/retcode/bl.js | grep -i "access-control-allow-origin"期待される出力:
access-control-allow-origin: *修正の検証
両方のステップを完了したら、ページを再読み込みします。window.onerror ハンドラは、完全なエラーを受け取ります。
"ReferenceError: bar is not defined", "http://another-domain.com/app.js", 2, 1, [Object Error]ソリューション 2: try...catch で呼び出しをラップ
サーバーの CORS ヘッダーを変更できない場合 (たとえば、制御できないサードパーティスクリプトの場合) は、クロスオリジン関数呼び出しを try...catch ブロックでラップします。
<!doctype html>
<html>
<head>
<title>Test page in http://test.com</title>
</head>
<body>
<script src="http://another-domain.com/app.js"></script>
<script>
window.onerror = function (message, url, line, column, error) {
console.log(message, url, line, column, error);
}
try {
foo(); // app.js で定義されている foo() を呼び出します
} catch (e) {
console.log(e);
throw e;
}
</script>
</body>
</html>catch ブロックは、スタックトレースを含む完全なエラーをキャプチャします。
ReferenceError: bar is not defined
at foo (http://another-domain.com/app.js:2:3)
at http://test.com/:15:3window.onerror ハンドラは引き続き "Script error." を受け取ります。キャプチャされたエラーを ARMS にレポートするには、catch ブロック内で SDK のエラーレポートメソッドを呼び出します。
__bl.error(error, pos);完全な API リファレンスについては、「SDK メソッド」をご参照ください。
ソリューション 1 (CORS) が推奨されるアプローチです。try...catch は、クロスオリジンヘッダーを構成できない場合にのみ使用してください。
ARMS でのスクリプトエラーのフィルタリング
スクリプトエラーがご利用のアプリケーションに影響を与えないサードパーティスクリプトから発生する場合、SDK の ignore パラメーターを使用して ARMS データからそれらをフィルタリングします。
ignore パラメーターは、3つのプロパティを持つオブジェクトを受け入れます。
ignore: {
ignoreUrls: [],
ignoreApis: [],
ignoreErrors: []
}スクリプトエラーをフィルタリングするには、ignoreErrors プロパティを使用します。これは、文字列、正規表現、関数、またはこれらのタイプを組み合わせた配列を受け入れます。
例: 正規表現を使用して、すべての「Script error.」メッセージをフィルタリングします。
__bl.setConfig({
ignore: {
ignoreErrors: /^Script error\.?$/
}
});