RequestClient.js 3.4 KB

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