Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions packages/@uppy/utils/src/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()
Expand All @@ -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()
Expand Down
10 changes: 9 additions & 1 deletion packages/@uppy/xhr-upload/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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
Expand All @@ -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')
}),
])

Expand Down
22 changes: 10 additions & 12 deletions packages/@uppy/xhr-upload/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ declare module '@uppy/core' {
}

function buildResponseError(
xhr: XMLHttpRequest,
xhr?: XMLHttpRequest,
err?: string | Error | NetworkError,
) {
let error = err
Expand Down Expand Up @@ -255,17 +255,15 @@ export default class XHRUpload<
if (error.name === 'AbortError') {
return undefined
}
if (error instanceof NetworkError) {
const request = error.request!

for (const file of files) {
this.uppy.emit(
'upload-error',
this.uppy.getFile(file.id),
buildResponseError(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,
)
}

throw error
Expand Down
Loading