Skip to content

Commit

Permalink
fix: update undiciRequestOption (#433)
Browse files Browse the repository at this point in the history
> 使用 undici 内部的 undiciRequestOption 类型,同时限制 headers 为
`IncomingHttpHeaders` 。

* 统一从 UndiciRequest 提取参数
* 去除无效的 `keepalive` 属性,undici 内部使用 reset
[ref](https://github.com/nodejs/undici/blob/main/docs/api/Dispatcher.md#dispatcherdispatchoptions-handler)
* typo 
----------------
> Use undici's internal undiciRequestOption type, while restricting
headers type to `IncomingHttpHeaders`.

* Uniformly fetch arguments type  from UndiciRequest
* Remove invalid `keepalive` attributes, undici internally uses reset
[ref](https://github.com/nodejs/undici/blob/main/docs/api/Dispatcher.md#dispatcherdispatchoptions
-handler)
* typo
  • Loading branch information
elrrrrrrr committed Feb 13, 2023
1 parent 35785ff commit 45157e8
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 18 deletions.
28 changes: 16 additions & 12 deletions src/HttpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { Readable, pipeline } from 'stream';
import stream from 'stream';
import { basename } from 'path';
import { createReadStream } from 'fs';
import { IncomingHttpHeaders } from 'http';
import { format as urlFormat } from 'url';
import { performance } from 'perf_hooks';
import {
Expand All @@ -33,6 +32,12 @@ import { RawResponseWithMeta, HttpClientResponse, SocketInfo } from './Response'
import { parseJSON, sleep, digestAuthHeader, globalId, performanceTime, isReadable } from './utils';
import symbols from './symbols';
import { initDiagnosticsChannel } from './diagnosticsChannel';
import type { IncomingHttpHeaders } from 'http';

type Exists<T> = T extends undefined ? never : T;
type UndiciRequestOption = Exists<Parameters<typeof undiciRequest>[1]>;
type PropertyShouldBe<T, K extends keyof T, V> = Omit<T, K> & { [P in K]: V };
type IUndiciRequestOption = PropertyShouldBe<UndiciRequestOption, 'headers', IncomingHttpHeaders>;

const PROTO_RE = /^https?:\/\//i;
const FormData = FormDataNative ?? FormDataNode;
Expand Down Expand Up @@ -84,8 +89,6 @@ export type ClientOptions = {
},
};

type UndiciRquestOptions = { dispatcher?: Dispatcher } & Omit<Dispatcher.RequestOptions, 'origin' | 'path' | 'method'> & Partial<Pick<Dispatcher.RequestOptions, 'method'>>;

// https://github.com/octet-stream/form-data
class BlobFromStream {
#stream;
Expand Down Expand Up @@ -180,7 +183,7 @@ export class HttpClient extends EventEmitter {
}

const method = (options?.method ?? 'GET').toUpperCase() as HttpMethod;
const orginalHeaders = options?.headers;
const originalHeaders = options?.headers;
const headers: IncomingHttpHeaders = {};
const args = {
retry: 0,
Expand Down Expand Up @@ -266,10 +269,10 @@ export class HttpClient extends EventEmitter {
headersTimeout = bodyTimeout = args.timeout;
}
}
if (orginalHeaders) {
if (originalHeaders) {
// convert headers to lower-case
for (const name in orginalHeaders) {
headers[name.toLowerCase()] = orginalHeaders[name];
for (const name in originalHeaders) {
headers[name.toLowerCase()] = originalHeaders[name];
}
}
// hidden user-agent
Expand Down Expand Up @@ -302,15 +305,16 @@ export class HttpClient extends EventEmitter {
}

try {
const requestOptions: UndiciRquestOptions = {
const requestOptions: IUndiciRequestOption = {
method,
keepalive: true,
maxRedirections: args.maxRedirects ?? 10,
headersTimeout,
headers,
bodyTimeout,
opaque: internalOpaque,
dispatcher: args.dispatcher ?? this.#dispatcher,
};

if (args.followRedirect === false) {
requestOptions.maxRedirections = 0;
}
Expand Down Expand Up @@ -429,7 +433,7 @@ export class HttpClient extends EventEmitter {
this.emit('request', reqMeta);
}

let response = await undiciRequest(requestUrl, requestOptions);
let response = await undiciRequest(requestUrl, requestOptions as UndiciRequestOption);
if (response.statusCode === 401 && response.headers['www-authenticate'] &&
!requestOptions.headers.authorization && args.digestAuth) {
// handle digest auth
Expand All @@ -442,11 +446,11 @@ export class HttpClient extends EventEmitter {
requestOptions.headers.authorization = digestAuthHeader(requestOptions.method!,
`${requestUrl.pathname}${requestUrl.search}`, authenticate, args.digestAuth);
debug('Request#%d %s: auth with digest header: %s', requestId, url, requestOptions.headers.authorization);
if (response.headers['set-cookie']) {
if (Array.isArray(response.headers['set-cookie'])) {
// FIXME: merge exists cookie header
requestOptions.headers.cookie = response.headers['set-cookie'].join(';');
}
response = await undiciRequest(requestUrl, requestOptions);
response = await undiciRequest(requestUrl, requestOptions as UndiciRequestOption);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Request.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Readable, Writable } from 'stream';
import { IncomingHttpHeaders } from 'http';
import type { IncomingHttpHeaders } from 'http';
import type Dispatcher from 'undici/types/dispatcher';
import type {
HttpClientResponse,
Expand Down
8 changes: 4 additions & 4 deletions test/options.timeout.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ describe('options.timeout.test.ts', () => {
await close();
});

it('should HeadersTimeout 10ms throw error', async () => {
it('should HeadersTimeout 1000ms throw error', async () => {
await assert.rejects(async () => {
await urllib.request(`${_url}?timeout=100`, {
await urllib.request(`${_url}?timeout=2000`, {
timeout: 10,
});
}, (err: any) => {
Expand All @@ -31,7 +31,7 @@ describe('options.timeout.test.ts', () => {
assert.equal(err.cause.message, 'Headers Timeout Error');
assert.equal(err.cause.code, 'UND_ERR_HEADERS_TIMEOUT');
}

assert.equal(err.res.status, -1);
assert(err.res.rt > 10, `actual ${err.res.rt}`);
assert.equal(typeof err.res.rt, 'number');
Expand All @@ -41,7 +41,7 @@ describe('options.timeout.test.ts', () => {

it('should BodyTimeout throw error', async () => {
await assert.rejects(async () => {
await urllib.request(`${_url}mock-bytes?timeout=300`, {
await urllib.request(`${_url}mock-bytes?timeout=2000`, {
timeout: 100,
});
}, (err: any) => {
Expand Down
2 changes: 1 addition & 1 deletion test/options.writeStream.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ describe('options.writeStream.test.ts', () => {
// console.log('writeStreamClosed');
});
await assert.rejects(async () => {
await urllib.request(`${_url}mock-bytes?size=1024&timeout=200`, {
await urllib.request(`${_url}mock-bytes?size=1024&timeout=2000`, {
writeStream,
timeout: 100,
});
Expand Down

0 comments on commit 45157e8

Please sign in to comment.