diff --git a/packages/@uppy/aws-s3-multipart/src/index.test.ts b/packages/@uppy/aws-s3-multipart/src/index.test.ts index 0b2c22aaf0..83a565a4ac 100644 --- a/packages/@uppy/aws-s3-multipart/src/index.test.ts +++ b/packages/@uppy/aws-s3-multipart/src/index.test.ts @@ -91,6 +91,7 @@ describe('AwsS3Multipart', () => { expect(uploadSuccessHandler.mock.calls[0][1]).toStrictEqual({ body: { ETag: 'test', + etag: 'test', location: 'http://example.com', }, status: 200, @@ -257,16 +258,16 @@ describe('AwsS3Multipart', () => { .mock.calls[0][1] expect(completeCall.parts).toEqual([ - { ETag: 'test', PartNumber: 1 }, - { ETag: 'test', PartNumber: 2 }, - { ETag: 'test', PartNumber: 3 }, - { ETag: 'test', PartNumber: 4 }, - { ETag: 'test', PartNumber: 5 }, - { ETag: 'test', PartNumber: 6 }, - { ETag: 'test', PartNumber: 7 }, - { ETag: 'test', PartNumber: 8 }, - { ETag: 'test', PartNumber: 9 }, - { ETag: 'test', PartNumber: 10 }, + { ETag: 'test', etag: 'test', PartNumber: 1 }, + { ETag: 'test', etag: 'test', PartNumber: 2 }, + { ETag: 'test', etag: 'test', PartNumber: 3 }, + { ETag: 'test', etag: 'test', PartNumber: 4 }, + { ETag: 'test', etag: 'test', PartNumber: 5 }, + { ETag: 'test', etag: 'test', PartNumber: 6 }, + { ETag: 'test', etag: 'test', PartNumber: 7 }, + { ETag: 'test', etag: 'test', PartNumber: 8 }, + { ETag: 'test', etag: 'test', PartNumber: 9 }, + { ETag: 'test', etag: 'test', PartNumber: 10 }, ]) }) diff --git a/packages/@uppy/aws-s3-multipart/src/index.ts b/packages/@uppy/aws-s3-multipart/src/index.ts index 2595d1bfe0..7722f0ee30 100644 --- a/packages/@uppy/aws-s3-multipart/src/index.ts +++ b/packages/@uppy/aws-s3-multipart/src/index.ts @@ -726,7 +726,7 @@ export default class AwsS3Multipart< ;(error as any).source = { status: 403 } reject(error) }) - xhr.addEventListener('load', (ev) => { + xhr.addEventListener('load', () => { cleanup() if ( @@ -748,9 +748,20 @@ export default class AwsS3Multipart< // todo make a proper onProgress API (breaking change) onProgress?.({ loaded: size, lengthComputable: true }) - // NOTE This must be allowed by CORS. - const etag = xhr.getResponseHeader('ETag') - const location = xhr.getResponseHeader('Location') + // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/getAllResponseHeaders#examples + const arr = xhr + .getAllResponseHeaders() + .trim() + .split(/[\r\n]+/) + // @ts-expect-error null is allowed to avoid inherited properties + const headersMap: Record = { __proto__: null } + for (const line of arr) { + const parts = line.split(': ') + const header = parts.shift()! + const value = parts.join(': ') + headersMap[header] = value + } + const { etag, location } = headersMap if (method.toUpperCase() === 'POST' && location === null) { // Not being able to read the Location header is not a fatal error. @@ -770,8 +781,8 @@ export default class AwsS3Multipart< onComplete?.(etag) resolve({ - ETag: etag, - ...(location ? { location } : undefined), + ...headersMap, + ETag: etag, // keep capitalised ETag for backwards compatiblity }) })