-
Notifications
You must be signed in to change notification settings - Fork 119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: impl fetch #542
feat: impl fetch #542
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// const { AsyncLocalStorage } = require('node:async_hooks'); | ||
import { AsyncLocalStorage } from 'node:async_hooks'; | ||
import symbols from './symbols.js'; | ||
import { Dispatcher } from 'undici'; | ||
|
||
// const RedirectHandler = require('../handler/redirect-handler') | ||
|
||
export interface FetchOpaque { | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore | ||
[symbols.kRequestId]: number; | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore | ||
[symbols.kRequestStartTime]: number; | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore | ||
[symbols.kEnableRequestTiming]: number; | ||
} | ||
Comment on lines
+8
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid using In the For example, you can declare the symbols as declare const kRequestId: unique symbol;
declare const kRequestStartTime: unique symbol;
declare const kEnableRequestTiming: unique symbol;
export interface FetchOpaque {
[kRequestId]: number;
[kRequestStartTime]: number;
[kEnableRequestTiming]: number;
} This approach allows TypeScript to recognize the symbol keys without suppressing type checks. |
||
|
||
// const internalOpaque = { | ||
// [symbols.kRequestId]: requestId, | ||
// [symbols.kRequestStartTime]: requestStartTime, | ||
// [symbols.kEnableRequestTiming]: !!(init.timing ?? true), | ||
// [symbols.kRequestTiming]: timing, | ||
// // [symbols.kRequestOriginalOpaque]: originalOpaque, | ||
// }; | ||
|
||
export interface OpaqueInterceptorOptions { | ||
opaqueLocalStorage: AsyncLocalStorage<FetchOpaque>; | ||
} | ||
|
||
export function fetchOpaqueInterceptor(opts: OpaqueInterceptorOptions) { | ||
const opaqueLocalStorage = opts?.opaqueLocalStorage; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unnecessary optional chaining for Since Apply this change: - const opaqueLocalStorage = opts?.opaqueLocalStorage;
+ const opaqueLocalStorage = opts.opaqueLocalStorage;
...
- const opaque = opaqueLocalStorage?.getStore();
+ const opaque = opaqueLocalStorage.getStore(); Also applies to: 36-36 |
||
return (dispatch: Dispatcher['dispatch']): Dispatcher['dispatch'] => { | ||
return function redirectInterceptor(opts: Dispatcher.DispatchOptions, handler: Dispatcher.DispatchHandlers) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Rename the interceptor function for clarity The function returned is named |
||
const opaque = opaqueLocalStorage?.getStore(); | ||
(handler as any).opaque = opaque; | ||
return dispatch(opts, handler); | ||
Comment on lines
+35
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid casting Casting Define a new interface: interface OpaqueDispatchHandlers extends Dispatcher.DispatchHandlers {
opaque?: FetchOpaque;
} Update the function signature: return function opaqueInterceptor(
opts: Dispatcher.DispatchOptions,
handler: OpaqueDispatchHandlers
) {
const opaque = opaqueLocalStorage.getStore();
handler.opaque = opaque;
return dispatch(opts, handler);
}; This approach maintains type integrity and avoids the pitfalls of using |
||
}; | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -37,7 +37,7 @@ import { HttpAgent, CheckAddressFunction } from './HttpAgent.js'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import type { IncomingHttpHeaders } from './IncomingHttpHeaders.js'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { RequestURL, RequestOptions, HttpMethod, RequestMeta } from './Request.js'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { RawResponseWithMeta, HttpClientResponse, SocketInfo } from './Response.js'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { parseJSON, digestAuthHeader, globalId, performanceTime, isReadable } from './utils.js'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { parseJSON, digestAuthHeader, globalId, performanceTime, isReadable, updateSocketInfo } from './utils.js'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import symbols from './symbols.js'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { initDiagnosticsChannel } from './diagnosticsChannel.js'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { HttpClientConnectTimeoutError, HttpClientRequestTimeoutError } from './HttpClientError.js'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -47,7 +47,28 @@ 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; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const PROTO_RE = /^https?:\/\//i; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export interface UnidiciTimingInfo { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
startTime: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
redirectStartTime: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
redirectEndTime: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
postRedirectStartTime: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
finalServiceWorkerStartTime: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
finalNetworkResponseStartTime: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
finalNetworkRequestStartTime: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
endTime: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
encodedBodySize: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
decodedBodySize: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
finalConnectionTimingInfo: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
domainLookupStartTime: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
domainLookupEndTime: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
connectionStartTime: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
connectionEndTime: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
secureConnectionStartTime: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// ALPNNegotiatedProtocol: undefined | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+52
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct Typo in Interface Name to 'UndiciTimingInfo' The interface name Apply this diff to correct the interface name: -export interface UnidiciTimingInfo {
+export interface UndiciTimingInfo { 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
function noop() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// noop | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -137,9 +158,11 @@ export type RequestContext = { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
requestStartTime?: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const channels = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const channels = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
request: diagnosticsChannel.channel('urllib:request'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
response: diagnosticsChannel.channel('urllib:response'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fetchRequest: diagnosticsChannel.channel('urllib:fetch:request'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fetchResponse: diagnosticsChannel.channel('urllib:fetch:response'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export type RequestDiagnosticsMessage = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -631,7 +654,7 @@ export class HttpClient extends EventEmitter { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
res.rt = performanceTime(requestStartTime); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// get real socket info from internalOpaque | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.#updateSocketInfo(socketInfo, internalOpaque); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
updateSocketInfo(socketInfo, internalOpaque); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const clientResponse: HttpClientResponse = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
opaque: originalOpaque, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -707,7 +730,7 @@ export class HttpClient extends EventEmitter { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
res.requestUrls.push(requestUrl.href); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
res.rt = performanceTime(requestStartTime); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.#updateSocketInfo(socketInfo, internalOpaque, rawError); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
updateSocketInfo(socketInfo, internalOpaque, rawError); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
channels.response.publish({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
request: reqMeta, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -729,40 +752,4 @@ export class HttpClient extends EventEmitter { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw err; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#updateSocketInfo(socketInfo: SocketInfo, internalOpaque: any, err?: any) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const socket = internalOpaque[symbols.kRequestSocket] ?? err?.[symbols.kErrorSocket]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (socket) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.id = socket[symbols.kSocketId]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.handledRequests = socket[symbols.kHandledRequests]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.handledResponses = socket[symbols.kHandledResponses]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (socket[symbols.kSocketLocalAddress]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.localAddress = socket[symbols.kSocketLocalAddress]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.localPort = socket[symbols.kSocketLocalPort]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (socket.remoteAddress) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.remoteAddress = socket.remoteAddress; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.remotePort = socket.remotePort; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.remoteFamily = socket.remoteFamily; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.bytesRead = socket.bytesRead; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.bytesWritten = socket.bytesWritten; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (socket[symbols.kSocketConnectErrorTime]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.connectErrorTime = socket[symbols.kSocketConnectErrorTime]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.attemptedRemoteAddresses = socket.autoSelectFamilyAttemptedAddresses; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.connectProtocol = socket[symbols.kSocketConnectProtocol]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.connectHost = socket[symbols.kSocketConnectHost]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.connectPort = socket[symbols.kSocketConnectPort]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (socket[symbols.kSocketConnectedTime]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.connectedTime = socket[symbols.kSocketConnectedTime]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (socket[symbols.kSocketRequestEndTime]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socketInfo.lastRequestEndTime = socket[symbols.kSocketRequestEndTime]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
socket[symbols.kSocketRequestEndTime] = new Date(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Remove commented-out code to improve code clarity
The file contains several blocks of commented-out code (lines 1-2, 6-7, and 20-27) which may no longer be needed. Removing these unused code sections can enhance readability and maintainability.
Also applies to: 6-7, 20-27