Merge pull request #1179 from syncthing/httperror

Handle HTTP errors on non-event requests (fixes #1120)
This commit is contained in:
Audrius Butkevicius 2015-01-05 17:45:18 +00:00
commit 010d5a0192
4 changed files with 57 additions and 21 deletions

View File

@ -125,6 +125,7 @@
"Syncthing is restarting.": "Syncthing is restarting.", "Syncthing is restarting.": "Syncthing is restarting.",
"Syncthing is upgrading.": "Syncthing is upgrading.", "Syncthing is upgrading.": "Syncthing is upgrading.",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…", "Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing seems to be experiencing a problem processing your request. Please reload your browser or restart Syncthing if the problem persists.",
"The aggregated statistics are publicly available at {%url%}.": "The aggregated statistics are publicly available at {{url}}.", "The aggregated statistics are publicly available at {%url%}.": "The aggregated statistics are publicly available at {{url}}.",
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.", "The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.",
"The device ID cannot be blank.": "The device ID cannot be blank.", "The device ID cannot be blank.": "The device ID cannot be blank.",

View File

@ -416,6 +416,14 @@
</p> </p>
</modal> </modal>
<!-- HTTP error modal -->
<modal id="httpError" status="danger" icon="exclamation-sign" title="{{'Connection Error' | translate}}">
<p translate>
Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.
</p>
</modal>
<!-- Restarting modal --> <!-- Restarting modal -->
<modal id="restarting" icon="refresh" title="{{'Restarting' | translate}}" status="info"> <modal id="restarting" icon="refresh" title="{{'Restarting' | translate}}" status="info">

View File

@ -10,7 +10,6 @@ angular.module('syncthing.core')
var restarting = false; var restarting = false;
function initController() { function initController() {
LocaleService.autoConfigLocale(); LocaleService.autoConfigLocale();
refreshSystem(); refreshSystem();
@ -21,11 +20,11 @@ angular.module('syncthing.core')
$http.get(urlbase + '/version').success(function (data) { $http.get(urlbase + '/version').success(function (data) {
$scope.version = data.version; $scope.version = data.version;
}); }).error($scope.emitHTTPError);
$http.get(urlbase + '/report').success(function (data) { $http.get(urlbase + '/report').success(function (data) {
$scope.reportData = data; $scope.reportData = data;
}); }).error($scope.emitHTTPError);
$http.get(urlbase + '/upgrade').success(function (data) { $http.get(urlbase + '/upgrade').success(function (data) {
$scope.upgradeInfo = data; $scope.upgradeInfo = data;
@ -106,6 +105,30 @@ angular.module('syncthing.core')
} }
}); });
$scope.$on('HTTPError', function (event, arg) {
// Emitted when a HTTP call fails. We use the status code to try
// to figure out what's wrong.
if (navigatingAway || !online) {
return;
}
console.log('HTTPError', arg);
online = false;
if (!restarting) {
if (arg.status === 0) {
// A network error, not an HTTP error
$scope.$emit('UIOffline');
} else if (arg.status >= 400 && arg.status <= 599) {
// A genuine HTTP error
$('#networkError').modal('hide');
$('#restarting').modal('hide');
$('#shutdown').modal('hide');
$('#httpError').modal();
}
}
});
$scope.$on('StateChanged', function (event, arg) { $scope.$on('StateChanged', function (event, arg) {
var data = arg.data; var data = arg.data;
if ($scope.model[data.folder]) { if ($scope.model[data.folder]) {
@ -183,7 +206,7 @@ angular.module('syncthing.core')
$http.get(urlbase + '/config/sync').success(function (data) { $http.get(urlbase + '/config/sync').success(function (data) {
$scope.configInSync = data.configInSync; $scope.configInSync = data.configInSync;
}); }).error($scope.emitHTTPError);
}); });
$scope.$on('DownloadProgress', function (event, arg) { $scope.$on('DownloadProgress', function (event, arg) {
@ -233,6 +256,10 @@ angular.module('syncthing.core')
console.log("DownloadProgress", $scope.progress); console.log("DownloadProgress", $scope.progress);
}); });
$scope.emitHTTPError = function (data, status, headers, config) {
$scope.$emit('HTTPError', {data: data, status: status, headers: headers, config: config});
};
var debouncedFuncs = {}; var debouncedFuncs = {};
function refreshFolder(folder) { function refreshFolder(folder) {
@ -242,7 +269,7 @@ angular.module('syncthing.core')
$http.get(urlbase + '/model?folder=' + encodeURIComponent(folder)).success(function (data) { $http.get(urlbase + '/model?folder=' + encodeURIComponent(folder)).success(function (data) {
$scope.model[folder] = data; $scope.model[folder] = data;
console.log("refreshFolder", folder, data); console.log("refreshFolder", folder, data);
}); }).error($scope.emitHTTPError);
}, 1000, true); }, 1000, true);
} }
debouncedFuncs[key](); debouncedFuncs[key]();
@ -289,7 +316,7 @@ angular.module('syncthing.core')
} }
$scope.announceServersFailed = failed; $scope.announceServersFailed = failed;
console.log("refreshSystem", data); console.log("refreshSystem", data);
}); }).error($scope.emitHTTPError);
} }
function refreshCompletion(device, folder) { function refreshCompletion(device, folder) {
@ -318,7 +345,7 @@ angular.module('syncthing.core')
$scope.completion[device]._total = tot / cnt; $scope.completion[device]._total = tot / cnt;
console.log("refreshCompletion", device, folder, $scope.completion[device]); console.log("refreshCompletion", device, folder, $scope.completion[device]);
}); }).error($scope.emitHTTPError);
}, 1000, true); }, 1000, true);
} }
debouncedFuncs[key](); debouncedFuncs[key]();
@ -345,25 +372,25 @@ angular.module('syncthing.core')
} }
$scope.connections = data; $scope.connections = data;
console.log("refreshConnections", data); console.log("refreshConnections", data);
}); }).error($scope.emitHTTPError);
} }
function refreshErrors() { function refreshErrors() {
$http.get(urlbase + '/errors').success(function (data) { $http.get(urlbase + '/errors').success(function (data) {
$scope.errors = data.errors; $scope.errors = data.errors;
console.log("refreshErrors", data); console.log("refreshErrors", data);
}); }).error($scope.emitHTTPError);
} }
function refreshConfig() { function refreshConfig() {
$http.get(urlbase + '/config').success(function (data) { $http.get(urlbase + '/config').success(function (data) {
updateLocalConfig(data); updateLocalConfig(data);
console.log("refreshConfig", data); console.log("refreshConfig", data);
}); }).error($scope.emitHTTPError);
$http.get(urlbase + '/config/sync').success(function (data) { $http.get(urlbase + '/config/sync').success(function (data) {
$scope.configInSync = data.configInSync; $scope.configInSync = data.configInSync;
}); }).error($scope.emitHTTPError);
} }
function refreshNeed(folder) { function refreshNeed(folder) {
@ -372,7 +399,7 @@ angular.module('syncthing.core')
console.log("refreshNeed", folder, data); console.log("refreshNeed", folder, data);
$scope.needed = data; $scope.needed = data;
} }
}); }).error($scope.emitHTTPError);
} }
var refreshDeviceStats = debounce(function () { var refreshDeviceStats = debounce(function () {
@ -383,7 +410,7 @@ angular.module('syncthing.core')
$scope.deviceStats[device].LastSeenDays = (new Date() - $scope.deviceStats[device].LastSeen) / 1000 / 86400; $scope.deviceStats[device].LastSeenDays = (new Date() - $scope.deviceStats[device].LastSeen) / 1000 / 86400;
} }
console.log("refreshDeviceStats", data); console.log("refreshDeviceStats", data);
}); }).error($scope.emitHTTPError);
}, 500); }, 500);
var refreshFolderStats = debounce(function () { var refreshFolderStats = debounce(function () {
@ -395,7 +422,7 @@ angular.module('syncthing.core')
} }
} }
console.log("refreshfolderStats", data); console.log("refreshfolderStats", data);
}); }).error($scope.emitHTTPError);
}, 500); }, 500);
$scope.refresh = function () { $scope.refresh = function () {
@ -576,7 +603,7 @@ angular.module('syncthing.core')
$http.get(urlbase + '/config/sync').success(function (data) { $http.get(urlbase + '/config/sync').success(function (data) {
$scope.configInSync = data.configInSync; $scope.configInSync = data.configInSync;
}); });
}); }).error($scope.emitHTTPError);
}; };
$scope.saveSettings = function () { $scope.saveSettings = function () {
@ -656,7 +683,7 @@ angular.module('syncthing.core')
restarting = true; restarting = true;
$http.post(urlbase + '/shutdown').success(function () { $http.post(urlbase + '/shutdown').success(function () {
$('#shutdown').modal(); $('#shutdown').modal();
}); }).error($scope.emitHTTPError);
$scope.configInSync = true; $scope.configInSync = true;
}; };
@ -857,7 +884,7 @@ angular.module('syncthing.core')
params: { current: newvalue } params: { current: newvalue }
}).success(function (data) { }).success(function (data) {
$scope.directoryList = data; $scope.directoryList = data;
}); }).error($scope.emitHTTPError);
}); });
$scope.editFolder = function (folderCfg) { $scope.editFolder = function (folderCfg) {
@ -1137,7 +1164,7 @@ angular.module('syncthing.core')
console.log("bumpFile", folder, data); console.log("bumpFile", folder, data);
$scope.needed = data; $scope.needed = data;
} }
}); }).error($scope.emitHTTPError);
}; };
// pseudo main. called on all definitions assigned // pseudo main. called on all definitions assigned

File diff suppressed because one or more lines are too long