From c0d18673f89deb885e4864472cad76c84c624552 Mon Sep 17 00:00:00 2001 From: TechQuery Date: Tue, 3 Sep 2024 06:52:51 +0800 Subject: [PATCH] [fix] some Compatibility bugs --- ReadMe.md | 1 + package.json | 2 +- source/HTTPRequest.ts | 73 +++++++++++++++---------------------- source/utility.ts | 2 +- test/Request-Client.spec.ts | 15 +++++++- 5 files changed, 46 insertions(+), 47 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index ab04188..113e3d6 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -45,6 +45,7 @@ npm install koajax + ``` diff --git a/package.json b/package.json index b1362ed..d33e399 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "koajax", - "version": "2.1.0-rc.0", + "version": "3.0.0", "license": "LGPL-3.0", "author": "shiy2008@gmail.com", "description": "HTTP Client based on Koa-like middlewares", diff --git a/source/HTTPRequest.ts b/source/HTTPRequest.ts index 021b845..27f95e7 100644 --- a/source/HTTPRequest.ts +++ b/source/HTTPRequest.ts @@ -1,15 +1,10 @@ import 'core-js/es/object/from-entries'; -import 'core-js/es/string/match-all'; import 'core-js/es/promise/with-resolvers'; -import 'web-streams-polyfill/polyfill/es5'; +import 'core-js/es/string/match-all'; +import type { ReadableStream } from 'web-streams-polyfill'; import { parseJSON } from 'web-utility'; -import { - parseDocument, - ProgressData, - readAs, - streamFromProgress -} from './utility'; +import { parseDocument, ProgressData, streamFromProgress } from './utility'; export enum BodyRequestMethods { POST = 'POST', @@ -81,8 +76,6 @@ export const parseHeaders = (raw: string): Response['headers'] => ) ); export function parseBody(raw: string, contentType: string): T { - if (contentType.includes('text')) return raw as T; - if (contentType.includes('json')) return parseJSON(raw); if (contentType.match(/html|xml/)) @@ -90,6 +83,8 @@ export function parseBody(raw: string, contentType: string): T { return parseDocument(raw, contentType) as T; } catch {} + if (contentType.includes('text')) return raw as T; + return new TextEncoder().encode(raw).buffer as T; } @@ -201,46 +196,35 @@ export function requestFetch({ body, signal: signals[0] && AbortSignal.any(signals) }); - const stream1 = Promise.withResolvers>(), - stream2 = Promise.withResolvers>(); - - responsePromise - .then(response => { - const streams = response.body.tee(); - - stream1.resolve(streams[0]); - stream2.resolve(streams[1]); - }) - .catch(reason => { - stream1.reject(reason); - stream2.reject(reason); - }); return { - response: parseResponse(responsePromise, stream1.promise, responseType), - download: iterateFetchBody(responsePromise, stream2.promise) + response: parseResponse(responsePromise, responseType), + download: iterateFetchBody(responsePromise) }; } export async function parseResponse( responsePromise: Promise, - streamPromise: Promise>, responseType: Request['responseType'] ): Promise> { - const response = await responsePromise; - const { status, statusText, headers } = response; + const { status, statusText, headers, body } = ( + await responsePromise + ).clone(); + const contentType = headers.get('Content-Type') || ''; const header = parseHeaders( [...headers].map(([key, value]) => `${key}: ${value}`).join('\n') ); - const stream = await streamPromise; - const body = + const rBody = status === 204 ? undefined - : await parseFetchBody(stream, contentType, responseType); - - return { status, statusText, headers: header, body }; + : await parseFetchBody( + body as ReadableStream, + contentType, + responseType + ); + return { status, statusText, headers: header, body: rBody }; } export async function parseFetchBody( @@ -258,21 +242,22 @@ export async function parseFetchBody( if (responseType === 'arraybuffer') return blob.arrayBuffer() as B; - const text = (await readAs(blob, 'text').result) as string; - - return parseBody(text, contentType); + return parseBody(await blob.text(), contentType); } export async function* iterateFetchBody( - responsePromise: Promise, - bodyPromise: Promise> + responsePromise: Promise ) { - const response = await responsePromise, - body = await bodyPromise; - const total = +response.headers.get('Content-Length'); + const { headers, body } = (await responsePromise).clone(); - for await (const { byteLength } of body) - yield { total, loaded: byteLength }; + const total = +headers.get('Content-Length'); + var loaded = 0; + + for await (const { byteLength } of body as ReadableStream) { + loaded += byteLength; + + yield { total, loaded }; + } } export const request = (options: Request): RequestResult => diff --git a/source/utility.ts b/source/utility.ts index 81d7404..cad7071 100644 --- a/source/utility.ts +++ b/source/utility.ts @@ -199,7 +199,7 @@ export const streamFromProgress = (target: T) => }; } ); -enum FileMethod { +export enum FileMethod { text = 'readAsText', dataURL = 'readAsDataURL', binaryString = 'readAsBinaryString', diff --git a/test/Request-Client.spec.ts b/test/Request-Client.spec.ts index 75df5c8..12835e6 100644 --- a/test/Request-Client.spec.ts +++ b/test/Request-Client.spec.ts @@ -1,6 +1,11 @@ -import { HTTPClient, request, requestFetch } from '../source'; +import { Blob } from 'buffer'; + +import { HTTPClient, ProgressData, request, requestFetch } from '../source'; import { XMLHttpRequest } from './XMLHttpRequest'; // @ts-ignore +// https://github.com/jsdom/jsdom/issues/2555#issuecomment-1864762292 +global.Blob = Blob; +// @ts-ignore global.XMLHttpRequest = XMLHttpRequest; describe('HTTP Request', () => { @@ -9,6 +14,14 @@ describe('HTTP Request', () => { path: 'https://api.github.com/users/TechQuery', responseType: 'json' }); + expect(Symbol.asyncIterator in download).toBeTruthy(); + + var progress: ProgressData = { loaded: 0, total: 0 }; + + for await (const part of download) progress = part; + + expect(progress.loaded).toBeGreaterThanOrEqual(progress.total); + const { body } = await response; expect(body).toMatchObject({ login: 'TechQuery' });