From 6c8ecb7b8e2eeef1c56863dca8d616463cebc4ea Mon Sep 17 00:00:00 2001 From: Jan <33495614+Jojo-1000@users.noreply.github.com> Date: Tue, 12 Dec 2023 23:17:12 +0100 Subject: [PATCH] Remove reliance on statusText for error messages. (#5056) HTTP/2 does not support statusText, and proxies might replace it. Use the response body instead. Closes #4729 --- .../WebServer/RESTMethods/RequestInfo.cs | 4 ++++ .../controllers/CommandlineController.js | 4 +--- .../scripts/controllers/ExportController.js | 5 +---- .../scripts/controllers/RestoreController.js | 20 +++++-------------- .../controllers/RestoreDirectController.js | 8 ++------ .../ngax/scripts/directives/backupEditUri.js | 6 ++---- .../ngax/scripts/services/AppService.js | 20 +++++++++++++++++++ .../webroot/ngax/scripts/services/AppUtils.js | 14 +++++-------- .../ngax/scripts/services/LogService.js | 4 +--- .../ngax/scripts/services/ServerStatus.js | 3 ++- 10 files changed, 43 insertions(+), 45 deletions(-) diff --git a/Duplicati/Server/WebServer/RESTMethods/RequestInfo.cs b/Duplicati/Server/WebServer/RESTMethods/RequestInfo.cs index c80b7edd8..43a498f46 100644 --- a/Duplicati/Server/WebServer/RESTMethods/RequestInfo.cs +++ b/Duplicati/Server/WebServer/RESTMethods/RequestInfo.cs @@ -92,6 +92,10 @@ namespace Duplicati.Server.WebServer.RESTMethods { Response.Status = code; Response.Reason = reason ?? "Error"; + if(item == null && reason != null) + { + item = new { Error = reason }; + } BodyWriter.WriteJsonObject(item); } diff --git a/Duplicati/Server/webroot/ngax/scripts/controllers/CommandlineController.js b/Duplicati/Server/webroot/ngax/scripts/controllers/CommandlineController.js index 38a38886e..326ca2e65 100644 --- a/Duplicati/Server/webroot/ngax/scripts/controllers/CommandlineController.js +++ b/Duplicati/Server/webroot/ngax/scripts/controllers/CommandlineController.js @@ -170,9 +170,7 @@ backupApp.controller('CommandlineController', function($scope, $routeParams, $lo $scope.Command = 'backup'; }, function(resp) { - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; + var message = AppService.responseErrorMessage(resp); DialogService.dialog(gettextCatalog.getString('Error'), gettextCatalog.getString('Failed to connect: {{message}}', { message: message })); } diff --git a/Duplicati/Server/webroot/ngax/scripts/controllers/ExportController.js b/Duplicati/Server/webroot/ngax/scripts/controllers/ExportController.js index 22949b9e0..2e75e8aca 100644 --- a/Duplicati/Server/webroot/ngax/scripts/controllers/ExportController.js +++ b/Duplicati/Server/webroot/ngax/scripts/controllers/ExportController.js @@ -35,10 +35,7 @@ backupApp.controller("ExportController", function($scope, $routeParams, AppServi }, function(resp) { $scope.Connecting = false; - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) { - message = resp.data.Message; - } + var message = AppService.responseErrorMessage(resp); DialogService.dialog(gettextCatalog.getString("Error"), gettextCatalog.getString("Failed to connect: {{message}}", { message: message })); } diff --git a/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreController.js b/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreController.js index 4ebec1005..a837d1acd 100644 --- a/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreController.js +++ b/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreController.js @@ -83,9 +83,7 @@ backupApp.controller('RestoreController', function ($rootScope, $scope, $routePa }, function(resp) { - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; + var message = AppService.responseErrorMessage(resp); $scope.connecting = false; $scope.ConnectionProgress = ''; @@ -112,9 +110,7 @@ backupApp.controller('RestoreController', function ($rootScope, $scope, $routePa $scope.connecting = false; $scope.ConnectionProgress = ''; - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; + var message = AppService.responseErrorMessage(resp); DialogService.dialog(gettextCatalog.getString('Error'), gettextCatalog.getString('Failed to fetch path information: {{message}}', { message: message })); }; @@ -291,9 +287,7 @@ backupApp.controller('RestoreController', function ($rootScope, $scope, $routePa }, function(resp) { $scope.Searching = false; - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; + var message = AppService.responseErrorMessage(resp); $scope.connecting = false; $scope.ConnectionProgress = ''; @@ -330,9 +324,7 @@ backupApp.controller('RestoreController', function ($rootScope, $scope, $routePa $scope.restore_step = 2; function handleError(resp) { - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; + var message = AppService.responseErrorMessage(resp); $scope.restore_step = 1; $scope.connecting = false; @@ -433,9 +425,7 @@ backupApp.controller('RestoreController', function ($rootScope, $scope, $routePa DialogService.dialog(gettextCatalog.getString('Error'), gettextCatalog.getString('Failed to restore files: {{message}}', { message: resp.data.ErrorMessage })); } }, function(resp) { - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; + var message = AppService.responseErrorMessage(resp); $scope.restore_step = 1; $scope.connecting = false; diff --git a/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreDirectController.js b/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreDirectController.js index bdc58a67b..8be1ab41d 100644 --- a/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreDirectController.js +++ b/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreDirectController.js @@ -65,9 +65,7 @@ backupApp.controller('RestoreDirectController', function ($rootScope, $scope, $l $scope.BackupID = resp.data.ID; $scope.fetchBackupTimes(); }, function(resp) { - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; + var message = AppService.responseErrorMessage(resp); $scope.connecting = false; $scope.ConnectionProgress = ''; @@ -98,9 +96,7 @@ backupApp.controller('RestoreDirectController', function ($rootScope, $scope, $l }, function(resp) { - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; + var message = AppService.responseErrorMessage(resp); if (message == 'encrypted-storage') message = gettextCatalog.getString('The target folder contains encrypted files, please supply the passphrase'); diff --git a/Duplicati/Server/webroot/ngax/scripts/directives/backupEditUri.js b/Duplicati/Server/webroot/ngax/scripts/directives/backupEditUri.js index d20a8105e..41cbbe02b 100644 --- a/Duplicati/Server/webroot/ngax/scripts/directives/backupEditUri.js +++ b/Duplicati/Server/webroot/ngax/scripts/directives/backupEditUri.js @@ -118,7 +118,7 @@ backupApp.directive('backupEditUri', function(gettextCatalog) { if (dlg != null) dlg.dismiss(); - var message = data.statusText; + var message = AppService.responseErrorMessage(data); if (!hasTriedCreate && message == 'missing-folder') { @@ -163,9 +163,7 @@ backupApp.directive('backupEditUri', function(gettextCatalog) { }, function(resp) { scope.Testing = false; - message = resp.statusText; - if (data.data != null && data.data.Message != null) - message = data.data.Message; + message = AppService.responseErrorMessage(resp); DialogService.dialog(gettextCatalog.getString('Error'), gettextCatalog.getString('Failed to import: ') + message); diff --git a/Duplicati/Server/webroot/ngax/scripts/services/AppService.js b/Duplicati/Server/webroot/ngax/scripts/services/AppService.js index d03654d11..3faac9575 100644 --- a/Duplicati/Server/webroot/ngax/scripts/services/AppService.js +++ b/Duplicati/Server/webroot/ngax/scripts/services/AppService.js @@ -123,4 +123,24 @@ backupApp.service('AppService', function($http, $cookies, $q, $cookies, DialogSe return installResponseHook($http.get(this.proxy_url == null ? rurl : this.proxy_url, setupConfig('GET', {}, null, rurl))); }; + + this.responseErrorMessage = function (resp) { + if (resp == null) { + return ''; + } + var message = resp.statusText; + if (resp.data != null) { + // Different ways to communicate error message (this should be refactored in the server at some point) + if (resp.data.Message != null) { + message = resp.data.Message; + } else if (resp.data.Error != null) { + message = resp.data.Error; + }else if (resp.data.message != null) { + message = resp.data.message; + } else if (resp.data.reason != null) { + message = resp.data.reason; + } + } + return message; + }; }); diff --git a/Duplicati/Server/webroot/ngax/scripts/services/AppUtils.js b/Duplicati/Server/webroot/ngax/scripts/services/AppUtils.js index 353ed5525..616d128a5 100644 --- a/Duplicati/Server/webroot/ngax/scripts/services/AppUtils.js +++ b/Duplicati/Server/webroot/ngax/scripts/services/AppUtils.js @@ -360,21 +360,17 @@ backupApp.service('AppUtils', function($rootScope, $timeout, $cookies, DialogSer this.connectionError = function(txt, msg) { if (typeof(txt) == typeof('')) { if (msg == null) - return function(msg) { - if (msg && msg.data && msg.data.Message) - DialogService.dialog(gettextCatalog.getString('Error'), txt + msg.data.Message); - else - DialogService.dialog(gettextCatalog.getString('Error'), txt + msg.statusText); + return function (msg) { + var msgText = AppService.responseErrorMessage(msg); + DialogService.dialog(gettextCatalog.getString('Error'), txt + msgText); }; } else { msg = txt; txt = ''; } - if (msg && msg.data && msg.data.Message) - DialogService.dialog(gettextCatalog.getString('Error'), txt + msg.data.Message); - else - DialogService.dialog(gettextCatalog.getString('Error'), txt + msg.statusText); + var msgText = AppService.responseErrorMessage(msg); + DialogService.dialog(gettextCatalog.getString('Error'), txt + msgText); }; this.generatePassphrase = function() { diff --git a/Duplicati/Server/webroot/ngax/scripts/services/LogService.js b/Duplicati/Server/webroot/ngax/scripts/services/LogService.js index 542997414..7d5923a4d 100644 --- a/Duplicati/Server/webroot/ngax/scripts/services/LogService.js +++ b/Duplicati/Server/webroot/ngax/scripts/services/LogService.js @@ -23,9 +23,7 @@ backupApp.service('LogService', function(AppService, DialogService, gettextCatal // $scope.Backup = BackupList.lookup[$scope.BackupID]; resolve({ current: current, complete: resp.data.length < pageSize }); }, function(resp) { - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; + var message = AppService.responseErrorMessage(resp); loadingData = false; DialogService.dialog('Error', gettextCatalog.getString('Failed to connect: {{message}}', { message: message })); diff --git a/Duplicati/Server/webroot/ngax/scripts/services/ServerStatus.js b/Duplicati/Server/webroot/ngax/scripts/services/ServerStatus.js index fa2770343..fd3097322 100644 --- a/Duplicati/Server/webroot/ngax/scripts/services/ServerStatus.js +++ b/Duplicati/Server/webroot/ngax/scripts/services/ServerStatus.js @@ -267,7 +267,8 @@ backupApp.service('ServerStatus', function($rootScope, $timeout, AppService, App var oldxsfrstate = state.xsfrerror; state.failedConnectionAttempts++; - state.xsfrerror = response.statusText.toLowerCase().indexOf('xsrf') >= 0; + var errorMessage = AppService.responseErrorMessage(response); + state.xsfrerror = errorMessage.toLowerCase().indexOf('xsrf') >= 0; // First failure, we ignore if (state.connectionState == 'connected' && state.failedConnectionAttempts == 1) {