| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent c9c6bf8 commit af226d0
23 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -952,6 +952,38 @@ const client = new Client("http://example.com").compose( | |||
| 952 | 952 | ); | |
| 953 | 953 | ``` | |
| 954 | 954 | ||
| 955 | + ##### `dump` | ||
| 956 | + | ||
| 957 | + The `dump` interceptor enables you to dump the response body from a request upon a given limit. | ||
| 958 | + | ||
| 959 | + **Options** | ||
| 960 | + - `maxSize` - The maximum size (in bytes) of the response body to dump. If the size of the request's body exceeds this value then the connection will be closed. Default: `1048576`. | ||
| 961 | + | ||
| 962 | + > The `Dispatcher#options` also gets extended with the options `dumpMaxSize`, `abortOnDumped`, and `waitForTrailers` which can be used to configure the interceptor at a request-per-request basis. | ||
| 963 | + | ||
| 964 | + **Example - Basic Dump Interceptor** | ||
| 965 | + | ||
| 966 | + ```js | ||
| 967 | + const { Client, interceptors } = require("undici"); | ||
| 968 | + const { dump } = interceptors; | ||
| 969 | + | ||
| 970 | + const client = new Client("http://example.com").compose( | ||
| 971 | + dump({ | ||
| 972 | + maxSize: 1024, | ||
| 973 | + }) | ||
| 974 | + ); | ||
| 975 | + | ||
| 976 | + // or | ||
| 977 | + client.dispatch( | ||
| 978 | + { | ||
| 979 | + path: "/", | ||
| 980 | + method: "GET", | ||
| 981 | + dumpMaxSize: 1024, | ||
| 982 | + }, | ||
| 983 | + handler | ||
| 984 | + ); | ||
| 985 | + ``` | ||
| 986 | + | ||
| 955 | 987 | ## Instance Events | |
| 956 | 988 | ||
| 957 | 989 | ### Event: `'connect'` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,7 +7,7 @@ const fetchImpl = require('./lib/web/fetch').fetch | |||
| 7 | 7 | module.exports.fetch = function fetch (resource, init = undefined) { | |
| 8 | 8 | return fetchImpl(resource, init).catch((err) => { | |
| 9 | 9 | if (err && typeof err === 'object') { | |
| 10 | - Error.captureStackTrace(err, this) | ||
| 10 | + Error.captureStackTrace(err) | ||
| 11 | 11 | } | |
| 12 | 12 | throw err | |
| 13 | 13 | }) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -40,7 +40,8 @@ module.exports.RedirectHandler = RedirectHandler | |||
| 40 | 40 | module.exports.createRedirectInterceptor = createRedirectInterceptor | |
| 41 | 41 | module.exports.interceptors = { | |
| 42 | 42 | redirect: require('./lib/interceptor/redirect'), | |
| 43 | - retry: require('./lib/interceptor/retry') | ||
| 43 | + retry: require('./lib/interceptor/retry'), | ||
| 44 | + dump: require('./lib/interceptor/dump') | ||
| 44 | 45 | } | |
| 45 | 46 | ||
| 46 | 47 | module.exports.buildConnector = buildConnector | |
@@ -108,7 +109,7 @@ module.exports.fetch = async function fetch (init, options = undefined) { | |||
| 108 | 109 | return await fetchImpl(init, options) | |
| 109 | 110 | } catch (err) { | |
| 110 | 111 | if (err && typeof err === 'object') { | |
| 111 | - Error.captureStackTrace(err, this) | ||
| 112 | + Error.captureStackTrace(err) | ||
| 112 | 113 | } | |
| 113 | 114 | ||
| 114 | 115 | throw err | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,7 +8,6 @@ module.exports = { | |||
| 8 | 8 | kQueue: Symbol('queue'), | |
| 9 | 9 | kConnect: Symbol('connect'), | |
| 10 | 10 | kConnecting: Symbol('connecting'), | |
| 11 | - kHeadersList: Symbol('headers list'), | ||
| 12 | 11 | kKeepAliveDefaultTimeout: Symbol('default keep alive timeout'), | |
| 13 | 12 | kKeepAliveMaxTimeout: Symbol('max keep alive timeout'), | |
| 14 | 13 | kKeepAliveTimeoutThreshold: Symbol('keep alive timeout threshold'), | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1101,7 +1101,7 @@ function writeStream ({ abort, body, client, request, socket, contentLength, hea | |||
| 1101 | 1101 | } | |
| 1102 | 1102 | } | |
| 1103 | 1103 | ||
| 1104 | - async function writeBuffer ({ abort, body, client, request, socket, contentLength, header, expectsPayload }) { | ||
| 1104 | + function writeBuffer ({ abort, body, client, request, socket, contentLength, header, expectsPayload }) { | ||
| 1105 | 1105 | try { | |
| 1106 | 1106 | if (!body) { | |
| 1107 | 1107 | if (contentLength === 0) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,123 @@ | |||
| 1 | + 'use strict' | ||
| 2 | + | ||
| 3 | + const util = require('../core/util') | ||
| 4 | + const { InvalidArgumentError, RequestAbortedError } = require('../core/errors') | ||
| 5 | + const DecoratorHandler = require('../handler/decorator-handler') | ||
| 6 | + | ||
| 7 | + class DumpHandler extends DecoratorHandler { | ||
| 8 | + #maxSize = 1024 * 1024 | ||
| 9 | + #abort = null | ||
| 10 | + #dumped = false | ||
| 11 | + #aborted = false | ||
| 12 | + #size = 0 | ||
| 13 | + #reason = null | ||
| 14 | + #handler = null | ||
| 15 | + | ||
| 16 | + constructor ({ maxSize }, handler) { | ||
| 17 | + super(handler) | ||
| 18 | + | ||
| 19 | + if (maxSize != null && (!Number.isFinite(maxSize) || maxSize < 1)) { | ||
| 20 | + throw new InvalidArgumentError('maxSize must be a number greater than 0') | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + this.#maxSize = maxSize ?? this.#maxSize | ||
| 24 | + this.#handler = handler | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + onConnect (abort) { | ||
| 28 | + this.#abort = abort | ||
| 29 | + | ||
| 30 | + this.#handler.onConnect(this.#customAbort.bind(this)) | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + #customAbort (reason) { | ||
| 34 | + this.#aborted = true | ||
| 35 | + this.#reason = reason | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + // TODO: will require adjustment after new hooks are out | ||
| 39 | + onHeaders (statusCode, rawHeaders, resume, statusMessage) { | ||
| 40 | + const headers = util.parseHeaders(rawHeaders) | ||
| 41 | + const contentLength = headers['content-length'] | ||
| 42 | + | ||
| 43 | + if (contentLength != null && contentLength > this.#maxSize) { | ||
| 44 | + throw new RequestAbortedError( | ||
| 45 | + `Response size (${contentLength}) larger than maxSize (${ | ||
| 46 | + this.#maxSize | ||
| 47 | + })` | ||
| 48 | + ) | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + if (this.#aborted) { | ||
| 52 | + return true | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + return this.#handler.onHeaders( | ||
| 56 | + statusCode, | ||
| 57 | + rawHeaders, | ||
| 58 | + resume, | ||
| 59 | + statusMessage | ||
| 60 | + ) | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + onError (err) { | ||
| 64 | + if (this.#dumped) { | ||
| 65 | + return | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + err = this.#reason ?? err | ||
| 69 | + | ||
| 70 | + this.#handler.onError(err) | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + onData (chunk) { | ||
| 74 | + this.#size = this.#size + chunk.length | ||
| 75 | + | ||
| 76 | + if (this.#size >= this.#maxSize) { | ||
| 77 | + this.#dumped = true | ||
| 78 | + | ||
| 79 | + if (this.#aborted) { | ||
| 80 | + this.#handler.onError(this.#reason) | ||
| 81 | + } else { | ||
| 82 | + this.#handler.onComplete([]) | ||
| 83 | + } | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + return true | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + onComplete (trailers) { | ||
| 90 | + if (this.#dumped) { | ||
| 91 | + return | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + if (this.#aborted) { | ||
| 95 | + this.#handler.onError(this.reason) | ||
| 96 | + return | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + this.#handler.onComplete(trailers) | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + function createDumpInterceptor ( | ||
| 104 | + { maxSize: defaultMaxSize } = { | ||
| 105 | + maxSize: 1024 * 1024 | ||
| 106 | + } | ||
| 107 | + ) { | ||
| 108 | + return dispatch => { | ||
| 109 | + return function Intercept (opts, handler) { | ||
| 110 | + const { dumpMaxSize = defaultMaxSize } = | ||
| 111 | + opts | ||
| 112 | + | ||
| 113 | + const dumpHandler = new DumpHandler( | ||
| 114 | + { maxSize: dumpMaxSize }, | ||
| 115 | + handler | ||
| 116 | + ) | ||
| 117 | + | ||
| 118 | + return dispatch(opts, dumpHandler) | ||
| 119 | + } | ||
| 120 | + } | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + module.exports = createDumpInterceptor | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,7 +1,7 @@ | |||
| 1 | 1 | 'use strict' | |
| 2 | 2 | ||
| 3 | 3 | const assert = require('node:assert') | |
| 4 | - const { kHeadersList } = require('../../core/symbols') | ||
| 4 | + const { getHeadersList: internalGetHeadersList } = require('../fetch/headers') | ||
| 5 | 5 | ||
| 6 | 6 | /** | |
| 7 | 7 | * @param {string} value | |
@@ -278,8 +278,10 @@ function stringify (cookie) { | |||
| 278 | 278 | let kHeadersListNode | |
| 279 | 279 | ||
| 280 | 280 | function getHeadersList (headers) { | |
| 281 | - if (headers[kHeadersList]) { | ||
| 282 | - return headers[kHeadersList] | ||
| 281 | + try { | ||
| 282 | + return internalGetHeadersList(headers) | ||
| 283 | + } catch { | ||
| 284 | + // fall-through | ||
| 283 | 285 | } | |
| 284 | 286 | ||
| 285 | 287 | if (!kHeadersListNode) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -385,6 +385,15 @@ function bodyMixinMethods (instance) { | |||
| 385 | 385 | 'Content-Type was not one of "multipart/form-data" or "application/x-www-form-urlencoded".' | |
| 386 | 386 | ) | |
| 387 | 387 | }, instance, false) | |
| 388 | + }, | ||
| 389 | + | ||
| 390 | + bytes () { | ||
| 391 | + // The bytes() method steps are to return the result of running consume body | ||
| 392 | + // with this and the following step given a byte sequence bytes: return the | ||
| 393 | + // result of creating a Uint8Array from bytes in this’s relevant realm. | ||
| 394 | + return consumeBody(this, (bytes) => { | ||
| 395 | + return new Uint8Array(bytes.buffer, 0, bytes.byteLength) | ||
| 396 | + }, instance, true) | ||
| 388 | 397 | } | |
| 389 | 398 | } | |
| 390 | 399 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments