私は Angular 1.3.15 を使用しています。例外を適切に処理することで、クライアント コードが無限エラー ループに入るのを防ぎたいと考えています。
例外の報告にSentryを使用していますが、クライアント コードから Sentry と通信していません。代わりに、クライアント コードから Web API (XHR を使用) に例外を報告し、Web API はそれを Sentry に報告します。
数日前に起こったことは、誰かが FireFox 10 で私たちのサイトを訪問したことでした。そのため、JavaScript のサポートが不十分なためにクライアント コードが無限エラー ループに陥り、例外を含む API を文字通りスパム/DoS 攻撃しました。私たちの API は NetScaler の背後にあるため、レート リミッターを設定することにしました。リクエストがレート リミッターに達した場合は、503 HTTP ステータス コード(Service Unavailable)を返すようになりました。
エラーは次のようになります。
([オブジェクト オブジェクト],[オブジェクト オブジェクト],(void 0))@/Static/Scripts/app/vendor/angular-translate/angular-translate.min.js:6 applyDirectivesToNode([オブジェクト配列],[オブジェクト HTMLAnchorElement] ,[オブジェクト オブジェクト],(void 0),(void 0),null,[オブジェクト配列],[オブジェクト配列],[オブジェクト オブジェクト])@/Static/Scripts/app/vendor/angular/angular.js:7498 compileNodes([オブジェクト プロキシ],(void 0))@/Static/Scripts/app/vendor/angular/angular.js:7040 compileNodes([オブジェクト プロキシ],(void 0))@/Static/Scripts/app/vendor /angular/angular.js:7054 compileNodes([オブジェクト プロキシ],(void 0))@/Static/Scripts/app/vendor/angular/angular.js:7054 compileNodes([オブジェクト プロキシ],(void 0))@ /Static/Scripts/app/vendor/angular/angular.js:7054 compileNodes([オブジェクト プロキシ],(void 0))@/Static/Scripts/app/vendor/angular/angular.js:7054 compileNodes([オブジェクト オブジェクト]、(ボイド0)、[オブジェクト オブジェクト],(void 0),(void 0),null)@/Static/Scripts/app/vendor/angular/angular.js:7054 ...
今問題に。クライアント コードに適切な例外処理を実装したいので、引き続き API/Sentry にエラーを報告しますが、HTTP 503 ステータス コード応答を受信した場合は、スクリプトの実行を直ちに停止して停止する必要があります。
$exceptionHandler
そこで、Angular モジュール構成にデコレーターを実装しようとしました。
// Flag indicating that the JavaScript execution should be stopped and Sentry should NOT be notified
var stopExecution = false;
$provide.decorator("$exceptionHandler", ['$delegate', function($delegate) {
return function(exception, cause) {
$delegate(exception, cause);
if(stopExecution) return;
// Call Sentry and report the exception
SentryServiceProvider.$get().captureException(exception)
.error(function (data, status, headers, config) {
if(status === 503) {
if(stopExecution) return;
stopExecution = true;
throw new Error('GOT AN 503 ERROR FROM API, STOPPING EXECUTION');
}
});
};
}]);
captureException()
SentryServiceProvider の私の関数は、POST 要求で API を呼び出し、例外メッセージとスタック トレースを JSON オブジェクトでペイロードとして送信し、$http promise を返します。
sentryService.captureException = function (ex) {
return $http.post(API_URL + '/sentry', { Message: ex.message, StackTrace: ex.stack });
};
問題は、無限ループにあるためです。コールバックに行くことはなくerror()
、API を永遠にスパムし続けます。クライアント コードで無限のエラー ループが発生しないようにするにはどうすればよいでしょうか?