From 2e1cf515c12dda92f5fbc17a085189210ce477ff Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 8 Aug 2017 16:37:14 +0200 Subject: [PATCH] Parse Sabre Exception in OC.Files.Client and file-upload In case of error, instead of a generic error message, an upload will display whichever message is returned in the Sabre Exception, if applicable. --- apps/files/js/file-upload.js | 35 ++++++++++++++---- core/js/files/client.js | 47 +++++++++++++++++++------ core/js/tests/specs/files/clientSpec.js | 18 ++++++++-- 3 files changed, 82 insertions(+), 18 deletions(-) diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index e3a012dc3dc4..4b1688a0da45 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -327,7 +327,23 @@ OC.FileUpload.prototype = { */ getResponse: function() { var response = this.data.response(); - if (typeof response.result !== 'string') { + if (response.errorThrown) { + // attempt parsing Sabre exception is available + var xml = response.jqXHR.responseXML; + if (xml.documentElement.localName === 'error' && xml.documentElement.namespaceURI === 'DAV:') { + var messages = xml.getElementsByTagNameNS('http://sabredav.org/ns', 'message'); + var exceptions = xml.getElementsByTagNameNS('http://sabredav.org/ns', 'exception'); + if (messages.length) { + response.message = messages[0].textContent; + } + if (exceptions.length) { + response.exception = exceptions[0].textContent; + } + return response; + } + } + + if (typeof response.result !== 'string' && response.result) { //fetch response from iframe response = $.parseJSON(response.result[0].body.innerText); if (!response) { @@ -976,6 +992,7 @@ OC.Uploader.prototype = _.extend({ status = upload.getResponseStatus(); } self.log('fail', e, upload); + self._hideProgressBar(); if (data.textStatus === 'abort') { self.showUploadCancelMessage(); @@ -997,7 +1014,12 @@ OC.Uploader.prototype = _.extend({ self.cancelUploads(); } else { // HTTP connection problem or other error - OC.Notification.show(data.errorThrown, {type: 'error'}); + var message = ''; + if (upload) { + var response = upload.getResponse(); + message = response.message; + } + OC.Notification.show(message || data.errorThrown, {type: 'error'}); } if (upload) { @@ -1139,16 +1161,17 @@ OC.Uploader.prototype = _.extend({ upload.done().then(function() { self._hideProgressBar(); self.trigger('done', e, upload); - }).fail(function(status) { + }).fail(function(status, response) { + var message = response.message; self._hideProgressBar(); if (status === 507) { // not enough space - OC.Notification.show(t('files', 'Not enough free space'), {type: 'error'}); + OC.Notification.show(message || t('files', 'Not enough free space'), {type: 'error'}); self.cancelUploads(); } else if (status === 409) { - OC.Notification.show(t('files', 'Target folder does not exist any more'), {type: 'error'}); + OC.Notification.show(message || t('files', 'Target folder does not exist any more'), {type: 'error'}); } else { - OC.Notification.show(t('files', 'Error when assembling chunks, status code {status}', {status: status}), {type: 'error'}); + OC.Notification.show(message || t('files', 'Error when assembling chunks, status code {status}', {status: status}), {type: 'error'}); } self.trigger('fail', e, data); }); diff --git a/core/js/files/client.js b/core/js/files/client.js index c93b4903e10a..dc1fef5b65fd 100644 --- a/core/js/files/client.js +++ b/core/js/files/client.js @@ -372,6 +372,26 @@ return status >= 200 && status <= 299; }, + /** + * Parse the Sabre exception out of the given response, if any + * + * @param {Object} response object + * @return {Object} array of parsed message and exception (only the first one) + */ + _getSabreException: function(response) { + var result = {}; + var xml = response.xhr.responseXML; + var messages = xml.getElementsByTagNameNS('http://sabredav.org/ns', 'message'); + var exceptions = xml.getElementsByTagNameNS('http://sabredav.org/ns', 'exception'); + if (messages.length) { + result.message = messages[0].textContent; + } + if (exceptions.length) { + result.exception = exceptions[0].textContent; + } + return result; + }, + /** * Returns the default PROPFIND properties to use during a call. * @@ -425,7 +445,8 @@ } deferred.resolve(result.status, results); } else { - deferred.reject(result.status); + result = _.extend(result, self._getSabreException(result)); + deferred.reject(result.status, result); } }); return promise; @@ -499,7 +520,8 @@ var results = self._parseResult(result.body); deferred.resolve(result.status, results); } else { - deferred.reject(result.status); + result = _.extend(result, self._getSabreException(result)); + deferred.reject(result.status, result); } }); return promise; @@ -538,7 +560,8 @@ if (self._isSuccessStatus(result.status)) { deferred.resolve(result.status, self._parseResult([result.body])[0]); } else { - deferred.reject(result.status); + result = _.extend(result, self._getSabreException(result)); + deferred.reject(result.status, result); } } ); @@ -568,7 +591,8 @@ if (self._isSuccessStatus(result.status)) { deferred.resolve(result.status, result.body); } else { - deferred.reject(result.status); + result = _.extend(result, self._getSabreException(result)); + deferred.reject(result.status, result); } } ); @@ -617,7 +641,8 @@ if (self._isSuccessStatus(result.status)) { deferred.resolve(result.status); } else { - deferred.reject(result.status); + result = _.extend(result, self._getSabreException(result)); + deferred.reject(result.status, result); } } ); @@ -641,7 +666,8 @@ if (self._isSuccessStatus(result.status)) { deferred.resolve(result.status); } else { - deferred.reject(result.status); + result = _.extend(result, self._getSabreException(result)); + deferred.reject(result.status, result); } } ); @@ -705,11 +731,12 @@ this._buildUrl(path), headers ).then( - function(response) { - if (self._isSuccessStatus(response.status)) { - deferred.resolve(response.status); + function(result) { + if (self._isSuccessStatus(result.status)) { + deferred.resolve(result.status); } else { - deferred.reject(response.status); + result = _.extend(result, self._getSabreException(result)); + deferred.reject(result.status, result); } } ); diff --git a/core/js/tests/specs/files/clientSpec.js b/core/js/tests/specs/files/clientSpec.js index f75998029a9c..6145f2d72b94 100644 --- a/core/js/tests/specs/files/clientSpec.js +++ b/core/js/tests/specs/files/clientSpec.js @@ -87,14 +87,28 @@ describe('OC.Files.Client tests', function() { promise.done(successHandler); promise.fail(failHandler); + var errorXml = + '' + + ' Sabre\\DAV\\Exception\\SomeException' + + ' Some error message' + + ''; + + var parser = new DOMParser(); + requestDeferred.resolve({ status: status, - body: '' + body: errorXml, + xhr: { + responseXML: parser.parseFromString(errorXml, 'application/xml') + } }); promise.then(function() { expect(failHandler.calledOnce).toEqual(true); - expect(failHandler.calledWith(status)).toEqual(true); + expect(failHandler.getCall(0).args[0]).toEqual(status); + expect(failHandler.getCall(0).args[1].status).toEqual(status); + expect(failHandler.getCall(0).args[1].message).toEqual('Some error message'); + expect(failHandler.getCall(0).args[1].exception).toEqual('Sabre\\DAV\\Exception\\SomeException'); expect(successHandler.notCalled).toEqual(true); });