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' });