diff --git a/packages/common/http/src/fetch.ts b/packages/common/http/src/fetch.ts index 716384872a5..687920c2858 100644 --- a/packages/common/http/src/fetch.ts +++ b/packages/common/http/src/fetch.ts @@ -145,7 +145,8 @@ export class FetchBackend implements HttpBackend { // Combine all chunks. const chunksAll = this.concatChunks(chunks, receivedLength); try { - body = this.parseBody(request, chunksAll); + const contentType = response.headers.get('Content-Type') ?? ''; + body = this.parseBody(request, chunksAll, contentType); } catch (error) { // Body loading or parsing failed observer.error(new HttpErrorResponse({ @@ -193,8 +194,8 @@ export class FetchBackend implements HttpBackend { } } - private parseBody(request: HttpRequest, binContent: Uint8Array): string|ArrayBuffer|Blob - |object|null { + private parseBody(request: HttpRequest, binContent: Uint8Array, contentType: string): string + |ArrayBuffer|Blob|object|null { switch (request.responseType) { case 'json': // stripping the XSSI when present @@ -203,7 +204,7 @@ export class FetchBackend implements HttpBackend { case 'text': return new TextDecoder().decode(binContent); case 'blob': - return new Blob([binContent]); + return new Blob([binContent], {type: contentType}); case 'arraybuffer': return binContent.buffer; } diff --git a/packages/common/http/test/fetch_spec.ts b/packages/common/http/test/fetch_spec.ts index 13d9f2b648a..0c765db9580 100644 --- a/packages/common/http/test/fetch_spec.ts +++ b/packages/common/http/test/fetch_spec.ts @@ -217,6 +217,16 @@ describe('FetchBackend', async () => { expect(res.body!.data).toBe('some data'); }); + it('handles a blob with a mime type', async () => { + const promise = trackEvents(backend.handle(TEST_POST.clone({responseType: 'blob'}))); + const type = 'aplication/pdf'; + fetchMock.mockFlush(HttpStatusCode.Ok, 'OK', new Blob(), {'Content-Type': type}); + const events = await promise; + expect(events.length).toBe(2); + const res = events[1] as HttpResponse; + expect(res.body?.type).toBe(type); + }); + it('emits unsuccessful responses via the error path', done => { backend.handle(TEST_POST).subscribe({ error: (err: HttpErrorResponse) => { @@ -400,12 +410,18 @@ export class MockFetchFactory extends FetchFactory { return this.promise; } - mockFlush(status: number, statusText: string, body?: string): void { + mockFlush( + status: number, statusText: string, body?: string|Blob, headers?: Record): + void { this.clearWarningTimeout?.(); - this.response.setupBodyStream(body); - - const response = - new Response(this.response.stream, {statusText, headers: this.response.headers}); + if (typeof body === 'string') { + this.response.setupBodyStream(body); + } else { + this.response.setBody(body); + } + const response = new Response( + this.response.stream, + {statusText, headers: {...this.response.headers, ...(headers ?? {})}}); // Have to be set outside the constructor because it might throw // RangeError: init["status"] must be in the range of 200 to 599, inclusive @@ -470,6 +486,11 @@ class MockFetchResponse { }, }); + public setBody(body: any) { + this.sub$.next(body); + this.sub$.complete(); + } + public setupBodyStream(body?: string) { if (body && this.progress.length) { this.headers['content-length'] = `${body.length}`;