|
@@ -2,56 +2,57 @@ const fetchWithNetworkError = require('@uppy/utils/lib/fetchWithNetworkError')
|
|
|
|
|
|
const ASSEMBLIES_ENDPOINT = '/assemblies'
|
|
|
|
|
|
-function fetchJSON (...args) {
|
|
|
- return fetchWithNetworkError(...args).then(response => {
|
|
|
- if (response.status === 429) {
|
|
|
- // If the server asks the client to rate limit, reschedule the request 2s later.
|
|
|
- // TODO: there are several instances of rate limiting accross the code base, having one global one could be useful.
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- setTimeout(() => fetchJSON(...args).then(resolve, reject), 2_000)
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- if (!response.ok) {
|
|
|
- const serverError = new Error(response.statusText)
|
|
|
- serverError.statusCode = response.status
|
|
|
-
|
|
|
- if (!`${args[0]}`.endsWith(ASSEMBLIES_ENDPOINT)) return Promise.reject(serverError)
|
|
|
-
|
|
|
- // Failed assembly requests should return a more detailed error in JSON.
|
|
|
- return response.json().then(assembly => {
|
|
|
- if (!assembly.error) throw serverError
|
|
|
-
|
|
|
- const error = new Error(assembly.error)
|
|
|
- error.details = assembly.message
|
|
|
- error.assembly = assembly
|
|
|
- if (assembly.assembly_id) {
|
|
|
- error.details += ` Assembly ID: ${assembly.assembly_id}`
|
|
|
- }
|
|
|
- throw error
|
|
|
- }, err => {
|
|
|
- // eslint-disable-next-line no-param-reassign
|
|
|
- err.cause = serverError
|
|
|
- throw err
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- return response.json()
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* A Barebones HTTP API client for Transloadit.
|
|
|
*/
|
|
|
module.exports = class Client {
|
|
|
#headers = {}
|
|
|
|
|
|
+ #fetchWithNetworkError
|
|
|
+
|
|
|
constructor (opts = {}) {
|
|
|
this.opts = opts
|
|
|
|
|
|
if (this.opts.client != null) {
|
|
|
this.#headers['Transloadit-Client'] = this.opts.client
|
|
|
}
|
|
|
+
|
|
|
+ this.#fetchWithNetworkError = this.opts.rateLimitedQueue.wrapPromiseFunction(fetchWithNetworkError)
|
|
|
+ }
|
|
|
+
|
|
|
+ #fetchJSON (...args) {
|
|
|
+ return this.#fetchWithNetworkError(...args).then(response => {
|
|
|
+ if (response.status === 429) {
|
|
|
+ this.opts.rateLimitedQueue.rateLimit(2_000)
|
|
|
+ return this.#fetchJSON(...args)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!response.ok) {
|
|
|
+ const serverError = new Error(response.statusText)
|
|
|
+ serverError.statusCode = response.status
|
|
|
+
|
|
|
+ if (!`${args[0]}`.endsWith(ASSEMBLIES_ENDPOINT)) return Promise.reject(serverError)
|
|
|
+
|
|
|
+ // Failed assembly requests should return a more detailed error in JSON.
|
|
|
+ return response.json().then(assembly => {
|
|
|
+ if (!assembly.error) throw serverError
|
|
|
+
|
|
|
+ const error = new Error(assembly.error)
|
|
|
+ error.details = assembly.message
|
|
|
+ error.assembly = assembly
|
|
|
+ if (assembly.assembly_id) {
|
|
|
+ error.details += ` Assembly ID: ${assembly.assembly_id}`
|
|
|
+ }
|
|
|
+ throw error
|
|
|
+ }, err => {
|
|
|
+ // eslint-disable-next-line no-param-reassign
|
|
|
+ err.cause = serverError
|
|
|
+ throw err
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ return response.json()
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -83,7 +84,7 @@ module.exports = class Client {
|
|
|
data.append('num_expected_upload_files', expectedFiles)
|
|
|
|
|
|
const url = new URL(ASSEMBLIES_ENDPOINT, `${this.opts.service}`).href
|
|
|
- return fetchJSON(url, {
|
|
|
+ return this.#fetchJSON(url, {
|
|
|
method: 'post',
|
|
|
headers: this.#headers,
|
|
|
body: data,
|
|
@@ -100,7 +101,7 @@ module.exports = class Client {
|
|
|
reserveFile (assembly, file) {
|
|
|
const size = encodeURIComponent(file.size)
|
|
|
const url = `${assembly.assembly_ssl_url}/reserve_file?size=${size}`
|
|
|
- return fetchJSON(url, { method: 'post', headers: this.#headers })
|
|
|
+ return this.#fetchJSON(url, { method: 'post', headers: this.#headers })
|
|
|
.catch((err) => this.#reportError(err, { assembly, file, url, type: 'API_ERROR' }))
|
|
|
}
|
|
|
|
|
@@ -121,7 +122,7 @@ module.exports = class Client {
|
|
|
|
|
|
const qs = `size=${size}&filename=${filename}&fieldname=${fieldname}&s3Url=${uploadUrl}`
|
|
|
const url = `${assembly.assembly_ssl_url}/add_file?${qs}`
|
|
|
- return fetchJSON(url, { method: 'post', headers: this.#headers })
|
|
|
+ return this.#fetchJSON(url, { method: 'post', headers: this.#headers })
|
|
|
.catch((err) => this.#reportError(err, { assembly, file, url, type: 'API_ERROR' }))
|
|
|
}
|
|
|
|
|
@@ -132,7 +133,7 @@ module.exports = class Client {
|
|
|
*/
|
|
|
cancelAssembly (assembly) {
|
|
|
const url = assembly.assembly_ssl_url
|
|
|
- return fetchJSON(url, { method: 'delete', headers: this.#headers })
|
|
|
+ return this.#fetchJSON(url, { method: 'delete', headers: this.#headers })
|
|
|
.catch((err) => this.#reportError(err, { url, type: 'API_ERROR' }))
|
|
|
}
|
|
|
|
|
@@ -142,7 +143,7 @@ module.exports = class Client {
|
|
|
* @param {string} url The status endpoint of the assembly.
|
|
|
*/
|
|
|
getAssemblyStatus (url) {
|
|
|
- return fetchJSON(url, { headers: this.#headers })
|
|
|
+ return this.#fetchJSON(url, { headers: this.#headers })
|
|
|
.catch((err) => this.#reportError(err, { url, type: 'STATUS_ERROR' }))
|
|
|
}
|
|
|
|
|
@@ -151,7 +152,7 @@ module.exports = class Client {
|
|
|
? `${err.message} (${err.details})`
|
|
|
: err.message
|
|
|
|
|
|
- return fetchJSON('https://transloaditstatus.com/client_error', {
|
|
|
+ return this.#fetchJSON('https://transloaditstatus.com/client_error', {
|
|
|
method: 'post',
|
|
|
body: JSON.stringify({
|
|
|
endpoint,
|