From 493446bf0090d3d0b38eda2c09058d538d369990 Mon Sep 17 00:00:00 2001 From: MK Date: Tue, 16 Jun 2026 21:53:12 +0800 Subject: [PATCH] feat: add rejectUnauthorized to RequestOptions Move `rejectUnauthorized` from the private `UrllibRequestOptions` interface to the public `RequestOptions` type so it can be passed to the top-level `request()`/`curl()` wrapper without a TypeScript error and without constructing a custom HttpClient. Since `allowH2` is already part of `RequestOptions`, the private `UrllibRequestOptions` interface became redundant and is removed; `request()`/`curl()` now use `RequestOptions` directly. --- README.md | 1 + src/Request.ts | 10 ++++ src/index.ts | 16 +------ ...tions.rejectUnauthorized.typecheck.test.ts | 48 +++++++++++++++++++ 4 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 test/options.rejectUnauthorized.typecheck.test.ts diff --git a/README.md b/README.md index 6f8c130c..dedc9d10 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ console.log('status: %s, body size: %d, headers: %j', res.status, data.length, r - **_timing_** Boolean - Enable timing or not, default is `true`. - **_socketPath_** String | null - request a unix socket service, default is `null`. - **_highWaterMark_** Number - default is `67108864`, 64 KiB. + - **_rejectUnauthorized_** Boolean - If `true`, the server certificate is verified against the list of supplied CAs and the request is rejected on failure. Set `false` to allow self-signed certificates. Default is `true`. Only effective on the top-level `request`/`curl` wrapper with its default dispatcher; it is ignored when calling `HttpClient.request()` directly or when a custom `dispatcher` is provided. #### Options: `options.data` diff --git a/src/Request.ts b/src/Request.ts index a16a291a..3723ae8c 100644 --- a/src/Request.ts +++ b/src/Request.ts @@ -156,6 +156,16 @@ export type RequestOptions = { /** Default: `64 KiB` */ highWaterMark?: number; signal?: globalThis.AbortSignal | EventEmitter; + /** + * If `true`, the server certificate is verified against the list of supplied CAs. If verification fails, the request + * promise is rejected. + * + * This option is only effective when using the top-level request/curl wrapper with its default dispatcher. It may be + * ignored when using `HttpClient.request()` directly or when `dispatcher` is explicitly provided. + * + * Default: `true` + */ + rejectUnauthorized?: boolean; }; export type RequestMeta = { diff --git a/src/index.ts b/src/index.ts index eee802ee..6946e5b4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -31,19 +31,7 @@ export function getDefaultHttpClient(rejectUnauthorized?: boolean, allowH2?: boo return client; } -interface UrllibRequestOptions extends RequestOptions { - /** - * If `true`, the server certificate is verified against the list of supplied CAs. An 'error' event is emitted if - * verification fails. Default: `true` - */ - rejectUnauthorized?: boolean; - // `allowH2` is inherited from RequestOptions. -} - -export async function request( - url: RequestURL, - options?: UrllibRequestOptions, -): Promise> { +export async function request(url: RequestURL, options?: RequestOptions): Promise> { if (options?.socketPath) { let domainSocketHttpclient = domainSocketHttpClients.get(options.socketPath); if (!domainSocketHttpclient) { @@ -63,7 +51,7 @@ export async function request( // import * as urllib from 'urllib'; // urllib.curl(url); // ``` -export async function curl(url: RequestURL, options?: UrllibRequestOptions): Promise> { +export async function curl(url: RequestURL, options?: RequestOptions): Promise> { return await request(url, options); } diff --git a/test/options.rejectUnauthorized.typecheck.test.ts b/test/options.rejectUnauthorized.typecheck.test.ts new file mode 100644 index 00000000..15618c95 --- /dev/null +++ b/test/options.rejectUnauthorized.typecheck.test.ts @@ -0,0 +1,48 @@ +import { strict as assert } from 'node:assert'; + +import { describe, it, beforeAll, afterAll } from 'vite-plus/test'; + +import urllib from '../src/index.js'; +import type { RequestOptions } from '../src/index.js'; +import { startServer } from './fixtures/server.js'; + +describe('options.rejectUnauthorized.typecheck.test.ts', () => { + let close: any; + let _url: string; + beforeAll(async () => { + const { closeServer, url } = await startServer({ https: true }); + close = closeServer; + _url = url; + }); + + afterAll(async () => { + await close(); + }); + + it('should accept rejectUnauthorized on RequestOptions type', async () => { + // Type check: rejectUnauthorized should be assignable on RequestOptions + const options: RequestOptions = { + rejectUnauthorized: false, + dataType: 'json', + }; + const response = await urllib.request(_url, options); + assert.equal(response.status, 200); + assert.equal(response.data.method, 'GET'); + }); + + it('should accept rejectUnauthorized = true on RequestOptions type', async () => { + const options: RequestOptions = { + rejectUnauthorized: true, + dataType: 'json', + }; + await assert.rejects( + async () => { + await urllib.request(_url, options); + }, + (err: any) => { + assert.match(err.message, /signed certificate/); + return true; + }, + ); + }); +});