transloadit: Add connection error reporting (#1484)

transloadit: Add connection error reporting
This commit is contained in:
Renée Kooi 2019-04-24 17:27:15 +02:00 committed by GitHub
commit 52fb8fdc57
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 9 deletions

View file

@ -101,9 +101,9 @@ PRs are welcome! Please do open an issue to discuss first if it's a big feature,
- [ ] !!! dashboard: Remove the Authorization required tooltip on the authentication screen https://github.com/transloadit/uppy/issues/1425
- [ ] @uppy/companion: investigate 423 and 500 issues with React Native + Url plugin when pause/resuming an upload
- [ ] docs: add docs on locales — how to use from NPM and CDN
- [ ] @uppy/transloadit: finish Transloadit-Client header on https://github.com/transloadit/uppy/tree/feature/transloadit-client
- [ ] companion: reports an error at first sign in. we did a hotfix in https://github.com/transloadit/uppy/pull/1478#issuecomment-485937942 but need a proper fix for that (@ife). Also: what about changing the location of that tooltip? So legit errors also don't block buttons?
## 1.0 Goals
What we need to do to release Uppy 1.0

View file

@ -4,6 +4,8 @@
module.exports = class Client {
constructor (opts = {}) {
this.opts = opts
this._reportError = this._reportError.bind(this)
}
/**
@ -31,7 +33,8 @@ module.exports = class Client {
})
data.append('num_expected_upload_files', expectedFiles)
return fetch(`${this.opts.service}/assemblies`, {
const url = `${this.opts.service}/assemblies`
return fetch(url, {
method: 'post',
body: data
}).then((response) => response.json()).then((assembly) => {
@ -43,7 +46,7 @@ module.exports = class Client {
}
return assembly
})
}).catch((err) => this._reportError(err, { url, type: 'API_ERROR' }))
}
/**
@ -54,8 +57,10 @@ module.exports = class Client {
*/
reserveFile (assembly, file) {
const size = encodeURIComponent(file.size)
return fetch(`${assembly.assembly_ssl_url}/reserve_file?size=${size}`, { method: 'post' })
const url = `${assembly.assembly_ssl_url}/reserve_file?size=${size}`
return fetch(url, { method: 'post' })
.then((response) => response.json())
.catch((err) => this._reportError(err, { assembly, file, url, type: 'API_ERROR' }))
}
/**
@ -69,13 +74,15 @@ module.exports = class Client {
return Promise.reject(new Error('File does not have an `uploadURL`.'))
}
const size = encodeURIComponent(file.size)
const url = encodeURIComponent(file.uploadURL)
const uploadUrl = encodeURIComponent(file.uploadURL)
const filename = encodeURIComponent(file.name)
const fieldname = 'file'
const qs = `size=${size}&filename=${filename}&fieldname=${fieldname}&s3Url=${url}`
return fetch(`${assembly.assembly_ssl_url}/add_file?${qs}`, { method: 'post' })
const qs = `size=${size}&filename=${filename}&fieldname=${fieldname}&s3Url=${uploadUrl}`
const url = `${assembly.assembly_ssl_url}/add_file?${qs}`
return fetch(url, { method: 'post' })
.then((response) => response.json())
.catch((err) => this._reportError(err, { assembly, file, url, type: 'API_ERROR' }))
}
/**
@ -84,8 +91,10 @@ module.exports = class Client {
* @param {object} assembly
*/
cancelAssembly (assembly) {
return fetch(assembly.assembly_ssl_url, { method: 'delete' })
const url = assembly.assembly_ssl_url
return fetch(url, { method: 'delete' })
.then((response) => response.json())
.catch((err) => this._reportError(err, { url, type: 'API_ERROR' }))
}
/**
@ -96,5 +105,46 @@ module.exports = class Client {
getAssemblyStatus (url) {
return fetch(url)
.then((response) => response.json())
.catch((err) => this._reportError(err, { url, type: 'STATUS_ERROR' }))
}
submitError (err, { endpoint, instance, assembly }) {
const message = err.details
? `${err.message} (${err.details})`
: err.message
return fetch('https://status.transloadit.com/client_error', {
method: 'post',
body: JSON.stringify({
endpoint,
instance,
assembly_id: assembly,
agent: typeof navigator !== 'undefined' ? navigator.userAgent : '',
error: message
})
}).then((response) => response.json())
}
_reportError (err, params) {
if (this.opts.errorReporting === false) {
throw err
}
const opts = {
type: params.type
}
if (params.assembly) {
opts.assembly = params.assembly.assembly_id
opts.instance = params.assembly.instance
}
if (params.url) {
opts.endpoint = params.url
}
this.submitError(err, opts).catch((_) => {
// not much we can do then is there
})
throw err
}
}

View file

@ -41,6 +41,7 @@ module.exports = class Transloadit extends Plugin {
const defaultOptions = {
service: 'https://api2.transloadit.com',
errorReporting: true,
waitForEncoding: false,
waitForMetadata: false,
alwaysRunAssembly: false,
@ -64,6 +65,7 @@ module.exports = class Transloadit extends Plugin {
this._prepareUpload = this._prepareUpload.bind(this)
this._afterUpload = this._afterUpload.bind(this)
this._onError = this._onError.bind(this)
this._onTusError = this._onTusError.bind(this)
this._onCancelAll = this._onCancelAll.bind(this)
this._onFileUploadURLAvailable = this._onFileUploadURLAvailable.bind(this)
this._onRestored = this._onRestored.bind(this)
@ -79,7 +81,8 @@ module.exports = class Transloadit extends Plugin {
}
this.client = new Client({
service: this.opts.service
service: this.opts.service,
errorReporting: this.opts.errorReporting
})
// Contains Assembly instances for in-progress Assemblies.
this.activeAssemblies = {}
@ -669,6 +672,17 @@ module.exports = class Transloadit extends Plugin {
})
}
_onTusError (err) {
if (err && /^tus: /.test(err.message)) {
const url = err.originalRequest && err.originalRequest.responseURL
? err.originalRequest.responseURL
: null
this.client.submitError(err, { url, type: 'TUS_ERROR' }).then((_) => {
// if we can't report the error that sucks
})
}
}
install () {
this.uppy.addPreProcessor(this._prepareUpload)
this.uppy.addPostProcessor(this._afterUpload)
@ -679,6 +693,9 @@ module.exports = class Transloadit extends Plugin {
// Handle cancellation.
this.uppy.on('cancel-all', this._onCancelAll)
// For error reporting.
this.uppy.on('upload-error', this._onTusError)
if (this.opts.importFromUploadURLs) {
// No uploader needed when importing; instead we take the upload URL from an existing uploader.
this.uppy.on('upload-success', this._onFileUploadURLAvailable)