RequestClient.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. 'use strict'
  2. const AuthError = require('./AuthError')
  3. // Remove the trailing slash so we can always safely append /xyz.
  4. function stripSlash (url) {
  5. return url.replace(/\/$/, '')
  6. }
  7. module.exports = class RequestClient {
  8. static VERSION = require('../package.json').version
  9. constructor (uppy, opts) {
  10. this.uppy = uppy
  11. this.opts = opts
  12. this.onReceiveResponse = this.onReceiveResponse.bind(this)
  13. }
  14. get hostname () {
  15. const { companion } = this.uppy.getState()
  16. const host = this.opts.companionUrl
  17. return stripSlash(companion && companion[host] ? companion[host] : host)
  18. }
  19. get defaultHeaders () {
  20. return {
  21. 'Accept': 'application/json',
  22. 'Content-Type': 'application/json'
  23. }
  24. }
  25. headers () {
  26. return Promise.resolve(Object.assign({}, this.defaultHeaders, this.opts.serverHeaders || {}))
  27. }
  28. _getPostResponseFunc (skip) {
  29. return (response) => {
  30. if (!skip) {
  31. return this.onReceiveResponse(response)
  32. }
  33. return response
  34. }
  35. }
  36. onReceiveResponse (response) {
  37. const state = this.uppy.getState()
  38. const companion = state.companion || {}
  39. const host = this.opts.companionUrl
  40. const headers = response.headers
  41. // Store the self-identified domain name for the Companion instance we just hit.
  42. if (headers.has('i-am') && headers.get('i-am') !== companion[host]) {
  43. this.uppy.setState({
  44. companion: Object.assign({}, companion, {
  45. [host]: headers.get('i-am')
  46. })
  47. })
  48. }
  49. return response
  50. }
  51. _getUrl (url) {
  52. if (/^(https?:|)\/\//.test(url)) {
  53. return url
  54. }
  55. return `${this.hostname}/${url}`
  56. }
  57. _json (res) {
  58. if (res.status === 401) {
  59. throw new AuthError()
  60. }
  61. if (res.status < 200 || res.status > 300) {
  62. throw new Error(`Failed request to ${res.url}. ${res.statusText}`)
  63. }
  64. return res.json()
  65. }
  66. get (path, skipPostResponse) {
  67. return new Promise((resolve, reject) => {
  68. this.headers().then((headers) => {
  69. fetch(this._getUrl(path), {
  70. method: 'get',
  71. headers: headers,
  72. credentials: 'same-origin'
  73. })
  74. .then(this._getPostResponseFunc(skipPostResponse))
  75. .then((res) => this._json(res).then(resolve))
  76. .catch((err) => {
  77. err = err.isAuthError ? err : new Error(`Could not get ${this._getUrl(path)}. ${err}`)
  78. reject(err)
  79. })
  80. })
  81. })
  82. }
  83. post (path, data, skipPostResponse) {
  84. return new Promise((resolve, reject) => {
  85. this.headers().then((headers) => {
  86. fetch(this._getUrl(path), {
  87. method: 'post',
  88. headers: headers,
  89. credentials: 'same-origin',
  90. body: JSON.stringify(data)
  91. })
  92. .then(this._getPostResponseFunc(skipPostResponse))
  93. .then((res) => this._json(res).then(resolve))
  94. .catch((err) => {
  95. err = err.isAuthError ? err : new Error(`Could not post ${this._getUrl(path)}. ${err}`)
  96. reject(err)
  97. })
  98. })
  99. })
  100. }
  101. delete (path, data, skipPostResponse) {
  102. return new Promise((resolve, reject) => {
  103. this.headers().then((headers) => {
  104. fetch(`${this.hostname}/${path}`, {
  105. method: 'delete',
  106. headers: headers,
  107. credentials: 'same-origin',
  108. body: data ? JSON.stringify(data) : null
  109. })
  110. .then(this._getPostResponseFunc(skipPostResponse))
  111. .then((res) => this._json(res).then(resolve))
  112. .catch((err) => {
  113. err = err.isAuthError ? err : new Error(`Could not delete ${this._getUrl(path)}. ${err}`)
  114. reject(err)
  115. })
  116. })
  117. })
  118. }
  119. }