| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -180,8 +180,6 @@ Implements [fetch](https://fetch.spec.whatwg.org/#fetch-method). | |||
| 180 | 180 | * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | |
| 181 | 181 | * https://fetch.spec.whatwg.org/#fetch-method | |
| 182 | 182 | ||
| 183 | - Only supported on Node 16.8+. | ||
| 184 | - | ||
| 185 | 183 | Basic usage example: | |
| 186 | 184 | ||
| 187 | 185 | ```js | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -50,7 +50,7 @@ Arguments: | |||
| 50 | 50 | ||
| 51 | 51 | ### `BalancedPool.removeUpstream(upstream)` | |
| 52 | 52 | ||
| 53 | - Removes an upstream that was previously addded. | ||
| 53 | + Removes an upstream that was previously added. | ||
| 54 | 54 | ||
| 55 | 55 | ### `BalancedPool.close([callback])` | |
| 56 | 56 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -209,6 +209,7 @@ Returns: `Boolean` - `false` if dispatcher is busy and further dispatch calls wo | |||
| 209 | 209 | * **onConnect** `(abort: () => void, context: object) => void` - Invoked before request is dispatched on socket. May be invoked multiple times when a request is retried when the request at the head of the pipeline fails. | |
| 210 | 210 | * **onError** `(error: Error) => void` - Invoked when an error has occurred. May not throw. | |
| 211 | 211 | * **onUpgrade** `(statusCode: number, headers: Buffer[], socket: Duplex) => void` (optional) - Invoked when request is upgraded. Required if `DispatchOptions.upgrade` is defined or `DispatchOptions.method === 'CONNECT'`. | |
| 212 | + * **onResponseStarted** `() => void` (optional) - Invoked when response is received, before headers have been read. | ||
| 212 | 213 | * **onHeaders** `(statusCode: number, headers: Buffer[], resume: () => void, statusText: string) => boolean` - Invoked when statusCode and headers have been received. May be invoked multiple times due to 1xx informational headers. Not required for `upgrade` requests. | |
| 213 | 214 | * **onData** `(chunk: Buffer) => boolean` - Invoked when response payload data is received. Not required for `upgrade` requests. | |
| 214 | 215 | * **onComplete** `(trailers: Buffer[]) => void` - Invoked when response payload and trailers have been received and the request has completed. Not required for `upgrade` requests. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,25 @@ | |||
| 1 | + # Util | ||
| 2 | + | ||
| 3 | + Utility API for third-party implementations of the dispatcher API. | ||
| 4 | + | ||
| 5 | + ## `parseHeaders(headers, [obj])` | ||
| 6 | + | ||
| 7 | + Receives a header object and returns the parsed value. | ||
| 8 | + | ||
| 9 | + Arguments: | ||
| 10 | + | ||
| 11 | + - **headers** `Record<string, string | string[]> | (Buffer | string | (Buffer | string)[])[]` (required) - Header object. | ||
| 12 | + | ||
| 13 | + - **obj** `Record<string, string | string[]>` (optional) - Object to specify a proxy object. The parsed value is assigned to this object. But, if **headers** is an object, it is not used. | ||
| 14 | + | ||
| 15 | + Returns: `Record<string, string | string[]>` If **headers** is an object, it is **headers**. Otherwise, if **obj** is specified, it is equivalent to **obj**. | ||
| 16 | + | ||
| 17 | + ## `headerNameToString(value)` | ||
| 18 | + | ||
| 19 | + Retrieves a header name and returns its lowercase value. | ||
| 20 | + | ||
| 21 | + Arguments: | ||
| 22 | + | ||
| 23 | + - **value** `string | Buffer` (required) - Header name. | ||
| 24 | + | ||
| 25 | + Returns: `string` | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -45,6 +45,10 @@ module.exports.createRedirectInterceptor = createRedirectInterceptor | |||
| 45 | 45 | ||
| 46 | 46 | module.exports.buildConnector = buildConnector | |
| 47 | 47 | module.exports.errors = errors | |
| 48 | + module.exports.util = { | ||
| 49 | + parseHeaders: util.parseHeaders, | ||
| 50 | + headerNameToString: util.headerNameToString | ||
| 51 | + } | ||
| 48 | 52 | ||
| 49 | 53 | function makeDispatcher (fn) { | |
| 50 | 54 | return (url, opts, handler) => { | |
@@ -98,58 +102,54 @@ function makeDispatcher (fn) { | |||
| 98 | 102 | module.exports.setGlobalDispatcher = setGlobalDispatcher | |
| 99 | 103 | module.exports.getGlobalDispatcher = getGlobalDispatcher | |
| 100 | 104 | ||
| 101 | - if (util.nodeMajor > 16 || (util.nodeMajor === 16 && util.nodeMinor >= 8)) { | ||
| 102 | - let fetchImpl = null | ||
| 103 | - module.exports.fetch = async function fetch (resource) { | ||
| 104 | - if (!fetchImpl) { | ||
| 105 | - fetchImpl = require('./lib/fetch').fetch | ||
| 106 | - } | ||
| 107 | - | ||
| 108 | - try { | ||
| 109 | - return await fetchImpl(...arguments) | ||
| 110 | - } catch (err) { | ||
| 111 | - if (typeof err === 'object') { | ||
| 112 | - Error.captureStackTrace(err, this) | ||
| 113 | - } | ||
| 105 | + let fetchImpl = null | ||
| 106 | + module.exports.fetch = async function fetch (resource) { | ||
| 107 | + if (!fetchImpl) { | ||
| 108 | + fetchImpl = require('./lib/fetch').fetch | ||
| 109 | + } | ||
| 114 | 110 | ||
| 115 | - throw err | ||
| 111 | + try { | ||
| 112 | + return await fetchImpl(...arguments) | ||
| 113 | + } catch (err) { | ||
| 114 | + if (typeof err === 'object') { | ||
| 115 | + Error.captureStackTrace(err, this) | ||
| 116 | 116 | } | |
| 117 | + | ||
| 118 | + throw err | ||
| 117 | 119 | } | |
| 118 | - module.exports.Headers = require('./lib/fetch/headers').Headers | ||
| 119 | - module.exports.Response = require('./lib/fetch/response').Response | ||
| 120 | - module.exports.Request = require('./lib/fetch/request').Request | ||
| 121 | - module.exports.FormData = require('./lib/fetch/formdata').FormData | ||
| 122 | - module.exports.File = require('./lib/fetch/file').File | ||
| 123 | - module.exports.FileReader = require('./lib/fileapi/filereader').FileReader | ||
| 120 | + } | ||
| 121 | + module.exports.Headers = require('./lib/fetch/headers').Headers | ||
| 122 | + module.exports.Response = require('./lib/fetch/response').Response | ||
| 123 | + module.exports.Request = require('./lib/fetch/request').Request | ||
| 124 | + module.exports.FormData = require('./lib/fetch/formdata').FormData | ||
| 125 | + module.exports.File = require('./lib/fetch/file').File | ||
| 126 | + module.exports.FileReader = require('./lib/fileapi/filereader').FileReader | ||
| 124 | 127 | ||
| 125 | - const { setGlobalOrigin, getGlobalOrigin } = require('./lib/fetch/global') | ||
| 128 | + const { setGlobalOrigin, getGlobalOrigin } = require('./lib/fetch/global') | ||
| 126 | 129 | ||
| 127 | - module.exports.setGlobalOrigin = setGlobalOrigin | ||
| 128 | - module.exports.getGlobalOrigin = getGlobalOrigin | ||
| 130 | + module.exports.setGlobalOrigin = setGlobalOrigin | ||
| 131 | + module.exports.getGlobalOrigin = getGlobalOrigin | ||
| 129 | 132 | ||
| 130 | - const { CacheStorage } = require('./lib/cache/cachestorage') | ||
| 131 | - const { kConstruct } = require('./lib/cache/symbols') | ||
| 133 | + const { CacheStorage } = require('./lib/cache/cachestorage') | ||
| 134 | + const { kConstruct } = require('./lib/cache/symbols') | ||
| 132 | 135 | ||
| 133 | - // Cache & CacheStorage are tightly coupled with fetch. Even if it may run | ||
| 134 | - // in an older version of Node, it doesn't have any use without fetch. | ||
| 135 | - module.exports.caches = new CacheStorage(kConstruct) | ||
| 136 | - } | ||
| 136 | + // Cache & CacheStorage are tightly coupled with fetch. Even if it may run | ||
| 137 | + // in an older version of Node, it doesn't have any use without fetch. | ||
| 138 | + module.exports.caches = new CacheStorage(kConstruct) | ||
| 137 | 139 | ||
| 138 | - if (util.nodeMajor >= 16) { | ||
| 139 | - const { deleteCookie, getCookies, getSetCookies, setCookie } = require('./lib/cookies') | ||
| 140 | + const { deleteCookie, getCookies, getSetCookies, setCookie } = require('./lib/cookies') | ||
| 140 | 141 | ||
| 141 | - module.exports.deleteCookie = deleteCookie | ||
| 142 | - module.exports.getCookies = getCookies | ||
| 143 | - module.exports.getSetCookies = getSetCookies | ||
| 144 | - module.exports.setCookie = setCookie | ||
| 142 | + module.exports.deleteCookie = deleteCookie | ||
| 143 | + module.exports.getCookies = getCookies | ||
| 144 | + module.exports.getSetCookies = getSetCookies | ||
| 145 | + module.exports.setCookie = setCookie | ||
| 145 | 146 | ||
| 146 | - const { parseMIMEType, serializeAMimeType } = require('./lib/fetch/dataURL') | ||
| 147 | + const { parseMIMEType, serializeAMimeType } = require('./lib/fetch/dataURL') | ||
| 147 | 148 | ||
| 148 | - module.exports.parseMIMEType = parseMIMEType | ||
| 149 | - module.exports.serializeAMimeType = serializeAMimeType | ||
| 150 | - } | ||
| 149 | + module.exports.parseMIMEType = parseMIMEType | ||
| 150 | + module.exports.serializeAMimeType = serializeAMimeType | ||
| 151 | 151 | ||
| 152 | - if (util.nodeMajor >= 18 && hasCrypto) { | ||
| 152 | + if (hasCrypto) { | ||
| 153 | 153 | const { WebSocket } = require('./lib/websocket/websocket') | |
| 154 | 154 | ||
| 155 | 155 | module.exports.WebSocket = WebSocket | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,15 +7,13 @@ const Pool = require('./pool') | |||
| 7 | 7 | const Client = require('./client') | |
| 8 | 8 | const util = require('./core/util') | |
| 9 | 9 | const createRedirectInterceptor = require('./interceptor/redirectInterceptor') | |
| 10 | - const { WeakRef, FinalizationRegistry } = require('./compat/dispatcher-weakref')() | ||
| 11 | 10 | ||
| 12 | 11 | const kOnConnect = Symbol('onConnect') | |
| 13 | 12 | const kOnDisconnect = Symbol('onDisconnect') | |
| 14 | 13 | const kOnConnectionError = Symbol('onConnectionError') | |
| 15 | 14 | const kMaxRedirections = Symbol('maxRedirections') | |
| 16 | 15 | const kOnDrain = Symbol('onDrain') | |
| 17 | 16 | const kFactory = Symbol('factory') | |
| 18 | - const kFinalizer = Symbol('finalizer') | ||
| 19 | 17 | const kOptions = Symbol('options') | |
| 20 | 18 | ||
| 21 | 19 | function defaultFactory (origin, opts) { | |
@@ -55,12 +53,6 @@ class Agent extends DispatcherBase { | |||
| 55 | 53 | this[kMaxRedirections] = maxRedirections | |
| 56 | 54 | this[kFactory] = factory | |
| 57 | 55 | this[kClients] = new Map() | |
| 58 | - this[kFinalizer] = new FinalizationRegistry(/* istanbul ignore next: gc is undeterministic */ key => { | ||
| 59 | - const ref = this[kClients].get(key) | ||
| 60 | - if (ref !== undefined && ref.deref() === undefined) { | ||
| 61 | - this[kClients].delete(key) | ||
| 62 | - } | ||
| 63 | - }) | ||
| 64 | 56 | ||
| 65 | 57 | const agent = this | |
| 66 | 58 | ||
@@ -83,12 +75,8 @@ class Agent extends DispatcherBase { | |||
| 83 | 75 | ||
| 84 | 76 | get [kRunning] () { | |
| 85 | 77 | let ret = 0 | |
| 86 | - for (const ref of this[kClients].values()) { | ||
| 87 | - const client = ref.deref() | ||
| 88 | - /* istanbul ignore next: gc is undeterministic */ | ||
| 89 | - if (client) { | ||
| 90 | - ret += client[kRunning] | ||
| 91 | - } | ||
| 78 | + for (const client of this[kClients].values()) { | ||
| 79 | + ret += client[kRunning] | ||
| 92 | 80 | } | |
| 93 | 81 | return ret | |
| 94 | 82 | } | |
@@ -101,45 +89,40 @@ class Agent extends DispatcherBase { | |||
| 101 | 89 | throw new InvalidArgumentError('opts.origin must be a non-empty string or URL.') | |
| 102 | 90 | } | |
| 103 | 91 | ||
| 104 | - const ref = this[kClients].get(key) | ||
| 92 | + let dispatcher = this[kClients].get(key) | ||
| 105 | 93 | ||
| 106 | - let dispatcher = ref ? ref.deref() : null | ||
| 107 | 94 | if (!dispatcher) { | |
| 108 | 95 | dispatcher = this[kFactory](opts.origin, this[kOptions]) | |
| 109 | 96 | .on('drain', this[kOnDrain]) | |
| 110 | 97 | .on('connect', this[kOnConnect]) | |
| 111 | 98 | .on('disconnect', this[kOnDisconnect]) | |
| 112 | 99 | .on('connectionError', this[kOnConnectionError]) | |
| 113 | 100 | ||
| 114 | - this[kClients].set(key, new WeakRef(dispatcher)) | ||
| 115 | - this[kFinalizer].register(dispatcher, key) | ||
| 101 | + // This introduces a tiny memory leak, as dispatchers are never removed from the map. | ||
| 102 | + // TODO(mcollina): remove te timer when the client/pool do not have any more | ||
| 103 | + // active connections. | ||
| 104 | + this[kClients].set(key, dispatcher) | ||
| 116 | 105 | } | |
| 117 | 106 | ||
| 118 | 107 | return dispatcher.dispatch(opts, handler) | |
| 119 | 108 | } | |
| 120 | 109 | ||
| 121 | 110 | async [kClose] () { | |
| 122 | 111 | const closePromises = [] | |
| 123 | - for (const ref of this[kClients].values()) { | ||
| 124 | - const client = ref.deref() | ||
| 125 | - /* istanbul ignore else: gc is undeterministic */ | ||
| 126 | - if (client) { | ||
| 127 | - closePromises.push(client.close()) | ||
| 128 | - } | ||
| 112 | + for (const client of this[kClients].values()) { | ||
| 113 | + closePromises.push(client.close()) | ||
| 129 | 114 | } | |
| 115 | + this[kClients].clear() | ||
| 130 | 116 | ||
| 131 | 117 | await Promise.all(closePromises) | |
| 132 | 118 | } | |
| 133 | 119 | ||
| 134 | 120 | async [kDestroy] (err) { | |
| 135 | 121 | const destroyPromises = [] | |
| 136 | - for (const ref of this[kClients].values()) { | ||
| 137 | - const client = ref.deref() | ||
| 138 | - /* istanbul ignore else: gc is undeterministic */ | ||
| 139 | - if (client) { | ||
| 140 | - destroyPromises.push(client.destroy(err)) | ||
| 141 | - } | ||
| 122 | + for (const client of this[kClients].values()) { | ||
| 123 | + destroyPromises.push(client.destroy(err)) | ||
| 142 | 124 | } | |
| 125 | + this[kClients].clear() | ||
| 143 | 126 | ||
| 144 | 127 | await Promise.all(destroyPromises) | |
| 145 | 128 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments