@uppy/xhr-upload: allow custom error message in onAfterResponse (#5578)

This commit is contained in:
Merlijn Vos 2025-01-07 14:49:12 +01:00 committed by GitHub
parent e567bb8d3a
commit f3a750da3b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 38 additions and 23 deletions

View file

@ -84,6 +84,16 @@ export function fetcher(
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve, reject) => {
const xhr = new XMLHttpRequest()
const onError = (error: Error) => {
if (shouldRetry(xhr) && retryCount < retries) {
setTimeout(() => {
requestWithRetry(retryCount + 1).then(resolve, reject)
}, delay(retryCount))
} else {
timer.done()
reject(error)
}
}
xhr.open(method, url, true)
xhr.withCredentials = withCredentials
@ -99,7 +109,15 @@ export function fetcher(
})
xhr.onload = async () => {
await onAfterResponse(xhr, retryCount)
try {
await onAfterResponse(xhr, retryCount)
} catch (err) {
// This is important as we need to emit the xhr
// over the upload-error event.
err.request = xhr
onError(err)
return
}
if (xhr.status >= 200 && xhr.status < 300) {
timer.done()
@ -114,16 +132,7 @@ export function fetcher(
}
}
xhr.onerror = () => {
if (shouldRetry(xhr) && retryCount < retries) {
setTimeout(() => {
requestWithRetry(retryCount + 1).then(resolve, reject)
}, delay(retryCount))
} else {
timer.done()
reject(new NetworkError(xhr.statusText, xhr))
}
}
xhr.onerror = () => onError(new NetworkError(xhr.statusText, xhr))
xhr.upload.onprogress = (event: ProgressEvent) => {
timer.progress()

View file

@ -79,7 +79,14 @@ describe('XHRUpload', () => {
id: 'XHRUpload',
endpoint: 'https://fake-endpoint.uppy.io',
shouldRetry,
async onAfterResponse(xhr) {
if (xhr.status === 400) {
// We want to test that we can define our own error message
throw new Error(JSON.parse(xhr.responseText).message)
}
},
})
const id = core.addFile({
type: 'image/png',
source: 'test',
@ -95,7 +102,7 @@ describe('XHRUpload', () => {
await Promise.all([
core.upload(),
event.then(([file, , response]) => {
event.then(([file, error, response]) => {
const newFile = core.getFile(id)
// error and response are set inside upload-error in core.
// When we subscribe to upload-error it is emitted before
@ -107,6 +114,7 @@ describe('XHRUpload', () => {
// might have changed in the meantime
expect(file).toEqual(newFile)
expect(response).toBeInstanceOf(XMLHttpRequest)
expect(error.message).toEqual('Oh no')
}),
])

View file

@ -82,7 +82,7 @@ declare module '@uppy/core' {
}
function buildResponseError(
xhr: XMLHttpRequest,
xhr?: XMLHttpRequest,
err?: string | Error | NetworkError,
) {
let error = err
@ -255,17 +255,15 @@ export default class XHRUpload<
if (error.name === 'AbortError') {
return undefined
}
if (error instanceof NetworkError) {
const request = error.request!
const request = error.request as XMLHttpRequest | undefined
for (const file of files) {
this.uppy.emit(
'upload-error',
this.uppy.getFile(file.id),
buildResponseError(request, error),
request,
)
}
for (const file of files) {
this.uppy.emit(
'upload-error',
this.uppy.getFile(file.id),
buildResponseError(request, error),
request,
)
}
throw error