xhr-error.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /**
  2. * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
  3. *
  4. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  5. * @author John Molakvoæ <skjnldsv@protonmail.com>
  6. *
  7. * @license GNU AGPL version 3 or any later version
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License as
  11. * published by the Free Software Foundation, either version 3 of the
  12. * License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. */
  23. import _ from 'underscore'
  24. import $ from 'jquery'
  25. import OC from './index'
  26. import Notification from './notification'
  27. /**
  28. * Warn users that the connection to the server was lost temporarily
  29. *
  30. * This function is throttled to prevent stacked notfications.
  31. * After 7sec the first notification is gone, then we can show another one
  32. * if necessary.
  33. */
  34. export const ajaxConnectionLostHandler = _.throttle(() => {
  35. Notification.showTemporary(t('core', 'Connection to server lost'))
  36. }, 7 * 1000, { trailing: false })
  37. /**
  38. * Process ajax error, redirects to main page
  39. * if an error/auth error status was returned.
  40. *
  41. * @param {XMLHttpRequest} xhr xhr request
  42. */
  43. export const processAjaxError = xhr => {
  44. // purposefully aborted request ?
  45. // OC._userIsNavigatingAway needed to distinguish ajax calls cancelled by navigating away
  46. // from calls cancelled by failed cross-domain ajax due to SSO redirect
  47. if (xhr.status === 0 && (xhr.statusText === 'abort' || xhr.statusText === 'timeout' || OC._reloadCalled)) {
  48. return
  49. }
  50. if (_.contains([302, 303, 307, 401], xhr.status) && OC.currentUser) {
  51. // sometimes "beforeunload" happens later, so need to defer the reload a bit
  52. setTimeout(function() {
  53. if (!OC._userIsNavigatingAway && !OC._reloadCalled) {
  54. let timer = 0
  55. const seconds = 5
  56. const interval = setInterval(function() {
  57. Notification.showUpdate(n('core', 'Problem loading page, reloading in %n second', 'Problem loading page, reloading in %n seconds', seconds - timer))
  58. if (timer >= seconds) {
  59. clearInterval(interval)
  60. OC.reload()
  61. }
  62. timer++
  63. }, 1000 // 1 second interval
  64. )
  65. // only call reload once
  66. OC._reloadCalled = true
  67. }
  68. }, 100)
  69. } else if (xhr.status === 0) {
  70. // Connection lost (e.g. WiFi disconnected or server is down)
  71. setTimeout(function() {
  72. if (!OC._userIsNavigatingAway && !OC._reloadCalled) {
  73. // TODO: call method above directly
  74. OC._ajaxConnectionLostHandler()
  75. }
  76. }, 100)
  77. }
  78. }
  79. /**
  80. * Registers XmlHttpRequest object for global error processing.
  81. *
  82. * This means that if this XHR object returns 401 or session timeout errors,
  83. * the current page will automatically be reloaded.
  84. *
  85. * @param {XMLHttpRequest} xhr xhr request
  86. */
  87. export const registerXHRForErrorProcessing = xhr => {
  88. const loadCallback = () => {
  89. if (xhr.readyState !== 4) {
  90. return
  91. }
  92. if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
  93. return
  94. }
  95. // fire jquery global ajax error handler
  96. $(document).trigger(new $.Event('ajaxError'), xhr)
  97. }
  98. const errorCallback = () => {
  99. // fire jquery global ajax error handler
  100. $(document).trigger(new $.Event('ajaxError'), xhr)
  101. }
  102. if (xhr.addEventListener) {
  103. xhr.addEventListener('load', loadCallback)
  104. xhr.addEventListener('error', errorCallback)
  105. }
  106. }