Skip to content

Commit

Permalink
feat: support AbortController (#493)
Browse files Browse the repository at this point in the history
closes #492
  • Loading branch information
fengmk2 committed Mar 9, 2024
1 parent 64965ee commit b81bbbb
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/HttpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ export class HttpClient extends EventEmitter {
bodyTimeout,
opaque: internalOpaque,
dispatcher: args.dispatcher ?? this.#dispatcher,
signal: args.signal,
};
if (typeof args.highWaterMark === 'number') {
requestOptions.highWaterMark = args.highWaterMark;
Expand Down
4 changes: 4 additions & 0 deletions src/Request.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Readable, Writable } from 'node:stream';
import type { EventEmitter } from 'node:events';
import type { Dispatcher } from 'undici';
import type { IncomingHttpHeaders } from './IncomingHttpHeaders.js';
import type { HttpClientResponse } from './Response.js';
Expand All @@ -10,6 +11,8 @@ export type RequestURL = string | URL;
export type FixJSONCtlCharsHandler = (data: string) => string;
export type FixJSONCtlChars = boolean | FixJSONCtlCharsHandler;

type AbortSignal = unknown;

export type RequestOptions = {
/** Request method, defaults to GET. Could be GET, POST, DELETE or PUT. Alias 'type'. */
method?: HttpMethod | Lowercase<HttpMethod>;
Expand Down Expand Up @@ -148,6 +151,7 @@ export type RequestOptions = {
reset?: boolean;
/** Default: `64 KiB` */
highWaterMark?: number;
signal?: AbortSignal | EventEmitter;
};

export type RequestMeta = {
Expand Down
56 changes: 56 additions & 0 deletions test/options.signal.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { strict as assert } from 'node:assert';
import { EventEmitter } from 'node:events';
import { describe, it, beforeAll, afterAll } from 'vitest';
import urllib from '../src';
import { startServer } from './fixtures/server';
import { sleep } from './utils';

describe('options.signal.test.ts', () => {
let close: any;
let _url: string;
beforeAll(async () => {
const { closeServer, url } = await startServer();
close = closeServer;
_url = url;
});

afterAll(async () => {
await close();
});

it.skipIf(typeof global.AbortController === 'undefined')('should throw error when AbortController abort', async () => {
await assert.rejects(async () => {
const abortController = new AbortController();
const p = urllib.request(`${_url}?timeout=2000`, {
signal: abortController.signal,
});
await sleep(100);
abortController.abort();
await p;
}, (err: any) => {
// console.error(err);
assert.equal(err.name, 'AbortError');
assert.equal(err.message, 'Request aborted');
assert.equal(err.code, 'UND_ERR_ABORTED');
return true;
});
});

it('should throw error when EventEmitter emit abort event', async () => {
await assert.rejects(async () => {
const ee = new EventEmitter();
const p = urllib.request(`${_url}?timeout=2000`, {
signal: ee,
});
await sleep(100);
ee.emit('abort');
await p;
}, (err: any) => {
// console.error(err);
assert.equal(err.name, 'AbortError');
assert.equal(err.message, 'Request aborted');
assert.equal(err.code, 'UND_ERR_ABORTED');
return true;
});
});
});

0 comments on commit b81bbbb

Please sign in to comment.