@zuplo/cli 6.70.71 → 6.71.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/@fastify/reply-from/node_modules/undici/docs/docs/api/Client.md +3 -0
- package/node_modules/@fastify/reply-from/node_modules/undici/docs/docs/api/Cookies.md +27 -0
- package/node_modules/@fastify/reply-from/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +1 -0
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/core/socks5-client.js +14 -4
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/core/socks5-utils.js +18 -4
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/agent.js +1 -1
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/balanced-pool.js +1 -1
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/client-h1.js +69 -1
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/client.js +3 -2
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/dispatcher-base.js +19 -0
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/pool.js +1 -1
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/proxy-agent.js +2 -1
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +45 -34
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/util/cache.js +8 -2
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/web/cookies/parse.js +17 -25
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/web/websocket/permessage-deflate.js +13 -31
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/web/websocket/receiver.js +80 -23
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/web/websocket/stream/websocketstream.js +8 -1
- package/node_modules/@fastify/reply-from/node_modules/undici/lib/web/websocket/websocket.js +8 -1
- package/node_modules/@fastify/reply-from/node_modules/undici/package.json +1 -1
- package/node_modules/@fastify/reply-from/node_modules/undici/types/client.d.ts +16 -0
- package/node_modules/@zuplo/core/package.json +1 -1
- package/node_modules/@zuplo/graphql/package.json +1 -1
- package/node_modules/@zuplo/openapi-tools/package.json +1 -1
- package/node_modules/@zuplo/otel/package.json +1 -1
- package/node_modules/@zuplo/runtime/package.json +1 -1
- package/node_modules/axios/CHANGELOG.md +52 -1
- package/node_modules/axios/README.md +30 -2
- package/node_modules/axios/dist/axios.js +350 -134
- package/node_modules/axios/dist/axios.min.js +3 -3
- package/node_modules/axios/dist/axios.min.js.map +1 -1
- package/node_modules/axios/dist/browser/axios.cjs +355 -90
- package/node_modules/axios/dist/esm/axios.js +355 -90
- package/node_modules/axios/dist/esm/axios.min.js +2 -2
- package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
- package/node_modules/axios/dist/node/axios.cjs +399 -104
- package/node_modules/axios/index.d.cts +2 -0
- package/node_modules/axios/index.d.ts +2 -0
- package/node_modules/axios/lib/adapters/fetch.js +113 -37
- package/node_modules/axios/lib/adapters/http.js +132 -43
- package/node_modules/axios/lib/core/Axios.js +3 -2
- package/node_modules/axios/lib/core/AxiosHeaders.js +10 -7
- package/node_modules/axios/lib/core/buildFullPath.js +29 -1
- package/node_modules/axios/lib/core/mergeConfig.js +34 -0
- package/node_modules/axios/lib/defaults/transitional.js +1 -0
- package/node_modules/axios/lib/env/data.js +1 -1
- package/node_modules/axios/lib/helpers/buildURL.js +5 -3
- package/node_modules/axios/lib/helpers/estimateDataURLDecodedBytes.js +16 -11
- package/node_modules/axios/lib/helpers/formDataToJSON.js +25 -3
- package/node_modules/axios/lib/helpers/resolveConfig.js +5 -3
- package/node_modules/axios/lib/helpers/shouldBypassProxy.js +33 -1
- package/node_modules/axios/lib/helpers/toFormData.js +40 -10
- package/node_modules/axios/lib/utils.js +75 -11
- package/node_modules/axios/package.json +1 -1
- package/node_modules/body-parser/README.md +16 -1
- package/node_modules/body-parser/index.js +4 -20
- package/node_modules/body-parser/lib/read.js +17 -17
- package/node_modules/body-parser/lib/types/json.js +60 -32
- package/node_modules/body-parser/lib/types/raw.js +3 -3
- package/node_modules/body-parser/lib/types/text.js +3 -3
- package/node_modules/body-parser/lib/types/urlencoded.js +16 -20
- package/node_modules/body-parser/lib/utils.js +18 -16
- package/node_modules/body-parser/node_modules/content-type/LICENSE +22 -0
- package/node_modules/body-parser/node_modules/content-type/README.md +69 -0
- package/node_modules/body-parser/node_modules/content-type/dist/index.d.ts +26 -0
- package/node_modules/body-parser/node_modules/content-type/dist/index.js +170 -0
- package/node_modules/body-parser/node_modules/content-type/dist/index.js.map +1 -0
- package/node_modules/body-parser/node_modules/content-type/package.json +52 -0
- package/node_modules/body-parser/node_modules/http-errors/HISTORY.md +186 -0
- package/node_modules/body-parser/node_modules/http-errors/LICENSE +23 -0
- package/node_modules/body-parser/node_modules/http-errors/README.md +169 -0
- package/node_modules/body-parser/node_modules/http-errors/index.js +290 -0
- package/node_modules/body-parser/node_modules/http-errors/package.json +54 -0
- package/node_modules/body-parser/package.json +23 -10
- package/node_modules/form-data/CHANGELOG.md +29 -2
- package/node_modules/form-data/README.md +4 -4
- package/node_modules/form-data/lib/form_data.js +14 -2
- package/node_modules/form-data/package.json +7 -7
- package/package.json +6 -6
package/node_modules/@fastify/reply-from/node_modules/undici/lib/web/websocket/permessage-deflate.js
CHANGED
|
@@ -8,40 +8,35 @@ const tail = Buffer.from([0x00, 0x00, 0xff, 0xff])
|
|
|
8
8
|
const kBuffer = Symbol('kBuffer')
|
|
9
9
|
const kLength = Symbol('kLength')
|
|
10
10
|
|
|
11
|
-
// Default maximum decompressed message size: 4 MB
|
|
12
|
-
const kDefaultMaxDecompressedSize = 4 * 1024 * 1024
|
|
13
|
-
|
|
14
11
|
class PerMessageDeflate {
|
|
15
12
|
/** @type {import('node:zlib').InflateRaw} */
|
|
16
13
|
#inflate
|
|
17
14
|
|
|
18
15
|
#options = {}
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
#aborted = false
|
|
22
|
-
|
|
23
|
-
/** @type {Function|null} */
|
|
24
|
-
#currentCallback = null
|
|
17
|
+
#maxPayloadSize = 0
|
|
25
18
|
|
|
26
19
|
/**
|
|
27
20
|
* @param {Map<string, string>} extensions
|
|
28
21
|
*/
|
|
29
|
-
constructor (extensions) {
|
|
22
|
+
constructor (extensions, options) {
|
|
30
23
|
this.#options.serverNoContextTakeover = extensions.has('server_no_context_takeover')
|
|
31
24
|
this.#options.serverMaxWindowBits = extensions.get('server_max_window_bits')
|
|
25
|
+
|
|
26
|
+
this.#maxPayloadSize = options.maxPayloadSize
|
|
32
27
|
}
|
|
33
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Decompress a compressed payload.
|
|
31
|
+
* @param {Buffer} chunk Compressed data
|
|
32
|
+
* @param {boolean} fin Final fragment flag
|
|
33
|
+
* @param {Function} callback Callback function
|
|
34
|
+
*/
|
|
34
35
|
decompress (chunk, fin, callback) {
|
|
35
36
|
// An endpoint uses the following algorithm to decompress a message.
|
|
36
37
|
// 1. Append 4 octets of 0x00 0x00 0xff 0xff to the tail end of the
|
|
37
38
|
// payload of the message.
|
|
38
39
|
// 2. Decompress the resulting data using DEFLATE.
|
|
39
|
-
|
|
40
|
-
if (this.#aborted) {
|
|
41
|
-
callback(new MessageSizeExceededError())
|
|
42
|
-
return
|
|
43
|
-
}
|
|
44
|
-
|
|
45
40
|
if (!this.#inflate) {
|
|
46
41
|
let windowBits = Z_DEFAULT_WINDOWBITS
|
|
47
42
|
|
|
@@ -64,23 +59,12 @@ class PerMessageDeflate {
|
|
|
64
59
|
this.#inflate[kLength] = 0
|
|
65
60
|
|
|
66
61
|
this.#inflate.on('data', (data) => {
|
|
67
|
-
if (this.#aborted) {
|
|
68
|
-
return
|
|
69
|
-
}
|
|
70
|
-
|
|
71
62
|
this.#inflate[kLength] += data.length
|
|
72
63
|
|
|
73
|
-
if (this.#inflate[kLength] >
|
|
74
|
-
|
|
64
|
+
if (this.#maxPayloadSize > 0 && this.#inflate[kLength] > this.#maxPayloadSize) {
|
|
65
|
+
callback(new MessageSizeExceededError())
|
|
75
66
|
this.#inflate.removeAllListeners()
|
|
76
|
-
this.#inflate.destroy()
|
|
77
67
|
this.#inflate = null
|
|
78
|
-
|
|
79
|
-
if (this.#currentCallback) {
|
|
80
|
-
const cb = this.#currentCallback
|
|
81
|
-
this.#currentCallback = null
|
|
82
|
-
cb(new MessageSizeExceededError())
|
|
83
|
-
}
|
|
84
68
|
return
|
|
85
69
|
}
|
|
86
70
|
|
|
@@ -93,14 +77,13 @@ class PerMessageDeflate {
|
|
|
93
77
|
})
|
|
94
78
|
}
|
|
95
79
|
|
|
96
|
-
this.#currentCallback = callback
|
|
97
80
|
this.#inflate.write(chunk)
|
|
98
81
|
if (fin) {
|
|
99
82
|
this.#inflate.write(tail)
|
|
100
83
|
}
|
|
101
84
|
|
|
102
85
|
this.#inflate.flush(() => {
|
|
103
|
-
if (
|
|
86
|
+
if (!this.#inflate) {
|
|
104
87
|
return
|
|
105
88
|
}
|
|
106
89
|
|
|
@@ -108,7 +91,6 @@ class PerMessageDeflate {
|
|
|
108
91
|
|
|
109
92
|
this.#inflate[kBuffer].length = 0
|
|
110
93
|
this.#inflate[kLength] = 0
|
|
111
|
-
this.#currentCallback = null
|
|
112
94
|
|
|
113
95
|
callback(null, full)
|
|
114
96
|
})
|
|
@@ -39,18 +39,27 @@ class ByteParser extends Writable {
|
|
|
39
39
|
/** @type {import('./websocket').Handler} */
|
|
40
40
|
#handler
|
|
41
41
|
|
|
42
|
+
/** @type {number} */
|
|
43
|
+
#maxFragments
|
|
44
|
+
|
|
45
|
+
/** @type {number} */
|
|
46
|
+
#maxPayloadSize
|
|
47
|
+
|
|
42
48
|
/**
|
|
43
49
|
* @param {import('./websocket').Handler} handler
|
|
44
50
|
* @param {Map<string, string>|null} extensions
|
|
51
|
+
* @param {{ maxFragments?: number, maxPayloadSize?: number }} [options]
|
|
45
52
|
*/
|
|
46
|
-
constructor (handler, extensions) {
|
|
53
|
+
constructor (handler, extensions, options = {}) {
|
|
47
54
|
super()
|
|
48
55
|
|
|
49
56
|
this.#handler = handler
|
|
50
57
|
this.#extensions = extensions == null ? new Map() : extensions
|
|
58
|
+
this.#maxFragments = options.maxFragments ?? 0
|
|
59
|
+
this.#maxPayloadSize = options.maxPayloadSize ?? 0
|
|
51
60
|
|
|
52
61
|
if (this.#extensions.has('permessage-deflate')) {
|
|
53
|
-
this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions))
|
|
62
|
+
this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions, options))
|
|
54
63
|
}
|
|
55
64
|
}
|
|
56
65
|
|
|
@@ -66,6 +75,19 @@ class ByteParser extends Writable {
|
|
|
66
75
|
this.run(callback)
|
|
67
76
|
}
|
|
68
77
|
|
|
78
|
+
#validatePayloadLength () {
|
|
79
|
+
if (
|
|
80
|
+
this.#maxPayloadSize > 0 &&
|
|
81
|
+
!isControlFrame(this.#info.opcode) &&
|
|
82
|
+
this.#info.payloadLength + this.#fragmentsBytes > this.#maxPayloadSize
|
|
83
|
+
) {
|
|
84
|
+
failWebsocketConnection(this.#handler, 1009, 'Payload size exceeds maximum allowed size')
|
|
85
|
+
return false
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return true
|
|
89
|
+
}
|
|
90
|
+
|
|
69
91
|
/**
|
|
70
92
|
* Runs whenever a new chunk is received.
|
|
71
93
|
* Callback is called whenever there are no more chunks buffering,
|
|
@@ -154,6 +176,10 @@ class ByteParser extends Writable {
|
|
|
154
176
|
if (payloadLength <= 125) {
|
|
155
177
|
this.#info.payloadLength = payloadLength
|
|
156
178
|
this.#state = parserStates.READ_DATA
|
|
179
|
+
|
|
180
|
+
if (!this.#validatePayloadLength()) {
|
|
181
|
+
return
|
|
182
|
+
}
|
|
157
183
|
} else if (payloadLength === 126) {
|
|
158
184
|
this.#state = parserStates.PAYLOADLENGTH_16
|
|
159
185
|
} else if (payloadLength === 127) {
|
|
@@ -178,6 +204,10 @@ class ByteParser extends Writable {
|
|
|
178
204
|
|
|
179
205
|
this.#info.payloadLength = buffer.readUInt16BE(0)
|
|
180
206
|
this.#state = parserStates.READ_DATA
|
|
207
|
+
|
|
208
|
+
if (!this.#validatePayloadLength()) {
|
|
209
|
+
return
|
|
210
|
+
}
|
|
181
211
|
} else if (this.#state === parserStates.PAYLOADLENGTH_64) {
|
|
182
212
|
if (this.#byteOffset < 8) {
|
|
183
213
|
return callback()
|
|
@@ -200,6 +230,10 @@ class ByteParser extends Writable {
|
|
|
200
230
|
|
|
201
231
|
this.#info.payloadLength = lower
|
|
202
232
|
this.#state = parserStates.READ_DATA
|
|
233
|
+
|
|
234
|
+
if (!this.#validatePayloadLength()) {
|
|
235
|
+
return
|
|
236
|
+
}
|
|
203
237
|
} else if (this.#state === parserStates.READ_DATA) {
|
|
204
238
|
if (this.#byteOffset < this.#info.payloadLength) {
|
|
205
239
|
return callback()
|
|
@@ -212,7 +246,9 @@ class ByteParser extends Writable {
|
|
|
212
246
|
this.#state = parserStates.INFO
|
|
213
247
|
} else {
|
|
214
248
|
if (!this.#info.compressed) {
|
|
215
|
-
this.writeFragments(body)
|
|
249
|
+
if (!this.writeFragments(body)) {
|
|
250
|
+
return
|
|
251
|
+
}
|
|
216
252
|
|
|
217
253
|
// If the frame is not fragmented, a message has been received.
|
|
218
254
|
// If the frame is fragmented, it will terminate with a fin bit set
|
|
@@ -224,29 +260,41 @@ class ByteParser extends Writable {
|
|
|
224
260
|
|
|
225
261
|
this.#state = parserStates.INFO
|
|
226
262
|
} else {
|
|
227
|
-
this.#extensions.get('permessage-deflate').decompress(
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
263
|
+
this.#extensions.get('permessage-deflate').decompress(
|
|
264
|
+
body,
|
|
265
|
+
this.#info.fin,
|
|
266
|
+
(error, data) => {
|
|
267
|
+
if (error) {
|
|
268
|
+
const code = error instanceof MessageSizeExceededError ? 1009 : 1007
|
|
269
|
+
failWebsocketConnection(this.#handler, code, error.message)
|
|
270
|
+
return
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (!this.writeFragments(data)) {
|
|
274
|
+
return
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Check cumulative fragment size
|
|
278
|
+
if (this.#maxPayloadSize > 0 && this.#fragmentsBytes > this.#maxPayloadSize) {
|
|
279
|
+
failWebsocketConnection(this.#handler, 1009, new MessageSizeExceededError().message)
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (!this.#info.fin) {
|
|
284
|
+
this.#state = parserStates.INFO
|
|
285
|
+
this.#loop = true
|
|
286
|
+
this.run(callback)
|
|
287
|
+
return
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments())
|
|
236
291
|
|
|
237
|
-
if (!this.#info.fin) {
|
|
238
|
-
this.#state = parserStates.INFO
|
|
239
292
|
this.#loop = true
|
|
293
|
+
this.#state = parserStates.INFO
|
|
240
294
|
this.run(callback)
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments())
|
|
245
|
-
|
|
246
|
-
this.#loop = true
|
|
247
|
-
this.#state = parserStates.INFO
|
|
248
|
-
this.run(callback)
|
|
249
|
-
})
|
|
295
|
+
},
|
|
296
|
+
this.#fragmentsBytes
|
|
297
|
+
)
|
|
250
298
|
|
|
251
299
|
this.#loop = false
|
|
252
300
|
break
|
|
@@ -305,8 +353,17 @@ class ByteParser extends Writable {
|
|
|
305
353
|
}
|
|
306
354
|
|
|
307
355
|
writeFragments (fragment) {
|
|
356
|
+
if (
|
|
357
|
+
this.#maxFragments > 0 &&
|
|
358
|
+
this.#fragments.length === this.#maxFragments
|
|
359
|
+
) {
|
|
360
|
+
failWebsocketConnection(this.#handler, 1008, 'Too many message fragments')
|
|
361
|
+
return false
|
|
362
|
+
}
|
|
363
|
+
|
|
308
364
|
this.#fragmentsBytes += fragment.length
|
|
309
365
|
this.#fragments.push(fragment)
|
|
366
|
+
return true
|
|
310
367
|
}
|
|
311
368
|
|
|
312
369
|
consumeFragments () {
|
|
@@ -258,7 +258,14 @@ class WebSocketStream {
|
|
|
258
258
|
#onConnectionEstablished (response, parsedExtensions) {
|
|
259
259
|
this.#handler.socket = response.socket
|
|
260
260
|
|
|
261
|
-
|
|
261
|
+
// Get options from dispatcher options
|
|
262
|
+
const maxFragments = this.#handler.controller.dispatcher?.webSocketOptions?.maxFragments
|
|
263
|
+
const maxPayloadSize = this.#handler.controller.dispatcher?.webSocketOptions?.maxPayloadSize
|
|
264
|
+
|
|
265
|
+
const parser = new ByteParser(this.#handler, parsedExtensions, {
|
|
266
|
+
maxFragments,
|
|
267
|
+
maxPayloadSize
|
|
268
|
+
})
|
|
262
269
|
parser.on('drain', () => this.#handler.onParserDrain())
|
|
263
270
|
parser.on('error', (err) => this.#handler.onParserError(err))
|
|
264
271
|
|
|
@@ -468,7 +468,14 @@ class WebSocket extends EventTarget {
|
|
|
468
468
|
// once this happens, the connection is open
|
|
469
469
|
this.#handler.socket = response.socket
|
|
470
470
|
|
|
471
|
-
const
|
|
471
|
+
const webSocketOptions = this.#handler.controller.dispatcher?.webSocketOptions
|
|
472
|
+
const maxFragments = webSocketOptions?.maxFragments
|
|
473
|
+
const maxPayloadSize = webSocketOptions?.maxPayloadSize
|
|
474
|
+
|
|
475
|
+
const parser = new ByteParser(this.#handler, parsedExtensions, {
|
|
476
|
+
maxFragments,
|
|
477
|
+
maxPayloadSize
|
|
478
|
+
})
|
|
472
479
|
parser.on('drain', () => this.#handler.onParserDrain())
|
|
473
480
|
parser.on('error', (err) => this.#handler.onParserError(err))
|
|
474
481
|
|
|
@@ -107,6 +107,8 @@ export declare namespace Client {
|
|
|
107
107
|
* @default 60000
|
|
108
108
|
*/
|
|
109
109
|
pingInterval?: number;
|
|
110
|
+
/** WebSocket-specific configuration options. */
|
|
111
|
+
webSocket?: WebSocketOptions;
|
|
110
112
|
}
|
|
111
113
|
export interface SocketInfo {
|
|
112
114
|
localAddress?: string
|
|
@@ -118,6 +120,20 @@ export declare namespace Client {
|
|
|
118
120
|
bytesWritten?: number
|
|
119
121
|
bytesRead?: number
|
|
120
122
|
}
|
|
123
|
+
export interface WebSocketOptions {
|
|
124
|
+
/**
|
|
125
|
+
* Maximum number of fragments in a message. Set to 0 to disable the limit.
|
|
126
|
+
* @default 131072
|
|
127
|
+
*/
|
|
128
|
+
maxFragments?: number;
|
|
129
|
+
/**
|
|
130
|
+
* Maximum allowed payload size in bytes for WebSocket messages.
|
|
131
|
+
* Applied to uncompressed messages, compressed frame payloads, and decompressed (permessage-deflate) messages.
|
|
132
|
+
* Set to 0 to disable the limit.
|
|
133
|
+
* @default 134217728 (128 MB)
|
|
134
|
+
*/
|
|
135
|
+
maxPayloadSize?: number;
|
|
136
|
+
}
|
|
121
137
|
}
|
|
122
138
|
|
|
123
139
|
export default Client
|
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v1.17.0 — June 1, 2026
|
|
4
|
+
|
|
5
|
+
This release adds Node HTTP zstd decompression, hardens config and release workflows, and fixes authentication, header, proxy, and type-handling regressions.
|
|
6
|
+
|
|
7
|
+
## 🔒 Security Fixes
|
|
8
|
+
|
|
9
|
+
* **Config Hardening:** Guarded `socketPath`, `params`, and `paramsSerializer` reads with own-property checks to prevent inherited prototype values from affecting request behavior, including SSRF-sensitive paths. (__#10901__, __#10922__)
|
|
10
|
+
* **Release Publishing:** Switched the publish workflow to npm staged publishing for safer, auditable package releases with provenance. (__#10926__)
|
|
11
|
+
|
|
12
|
+
## 🚀 New Features
|
|
13
|
+
|
|
14
|
+
* **HTTP Compression:** Added Node HTTP adapter support for zstd response decompression, with `transitional.advertiseZstdAcceptEncoding` controlling whether `zstd` is advertised in `Accept-Encoding`. (__#6792__, __#10920__)
|
|
15
|
+
|
|
16
|
+
## 🐛 Bug Fixes
|
|
17
|
+
|
|
18
|
+
* **Authentication Handling:** Restored Basic auth on same-origin Node redirects while continuing to strip credentials cross-origin, and aligned the fetch adapter with HTTP adapter behavior for URL-embedded Basic auth. (__#10929__, __#10896__)
|
|
19
|
+
* **Proxy TLS:** Preserved user `httpsAgent` TLS options when tunneling HTTPS requests through HTTP CONNECT proxies. (__#10957__)
|
|
20
|
+
* **React Native FormData:** Cleared default `Content-Type` for React Native `FormData` so multipart boundaries can be generated correctly. (__#10898__)
|
|
21
|
+
* **Headers:** Silently skipped empty or whitespace-only header names instead of throwing, matching parsed-header behavior and avoiding React Native response crashes. (__#10875__)
|
|
22
|
+
* **Request Data Merging:** Preserved enumerable symbol keys when cloning plain request data through axios merge logic. (__#10812__)
|
|
23
|
+
* **Bundler Compatibility:** Converted `resolveConfig` from an arrow default export to a named function export to avoid webpack and Babel transform interop failures. (__#10891__)
|
|
24
|
+
* **Types:** Corrected `AxiosHeaders.toJSON()` return types and updated CommonJS `isCancel` typings to narrow to `CanceledError<T>`. (__#10956__, __#10952__)
|
|
25
|
+
* **Build Tooling:** Avoided emitting a null `Authorization` header from the GitHub build helper when `GITHUB_TOKEN` is unset. (__#10931__)
|
|
26
|
+
|
|
27
|
+
## 🔧 Maintenance & Chores
|
|
28
|
+
|
|
29
|
+
* **HTTP/2 Internals:** Extracted `Http2Sessions` into its own helper module and added direct unit coverage for session pooling, timeout, and cleanup behavior. (__#10861__)
|
|
30
|
+
* **Package Publishing:** Reduced published package size by switching to a `files` allowlist and dropping unneeded unminified bundle source maps. (__#10939__)
|
|
31
|
+
* **CI and Release Automation:** Added bundle-size reporting, moved reports to the job summary, fixed bundle-size comparison coverage, added Node 26 to the matrix, pinned npm for staged publishing, and prepared the 1.17.0 release. (__#10907__, __#10911__, __#10916__, __#10927__, __#10935__, __#10983__)
|
|
32
|
+
* **Developer Workflow:** Added a dev container and iterated on OpenSpec workflow files before removing them from the release branch. (__#10925__, __#10914__, __#10958__)
|
|
33
|
+
* **Documentation and Policy:** Updated disclosure, contributor, collaboration, threat-model, advanced docs, README badges, release notes, moderator configuration, and project metadata. (__#10890__, __#10889__, __#10921__, __#10945__, __#10905__, __#10933__, __#10915__, __#10887__, __#10955__)
|
|
34
|
+
* **Dependencies:** Bumped Babel tooling, Commitlint, ESLint, Rollup, Globals, Vitest, Playwright, `fs-extra`, `qs`, docs dependencies, and GitHub Actions dependencies including `actions/dependency-review-action` and `zizmorcore/zizmor-action`. (__#10871__, __#10879__, __#10918__, __#10919__, __#10934__, __#10947__, __#10954__, __#10960__)
|
|
35
|
+
|
|
36
|
+
## 🌟 New Contributors
|
|
37
|
+
|
|
38
|
+
We are thrilled to welcome our new contributors. Thank you for helping improve axios:
|
|
39
|
+
|
|
40
|
+
* __@BasixKOR__ (__#6792__)
|
|
41
|
+
* __@carladams1299-lab__ (__#10861__)
|
|
42
|
+
* __@LaplaceYoung__ (__#10812__)
|
|
43
|
+
* __@JamieMagee__ (__#10939__)
|
|
44
|
+
* __@RonGamzu__ (__#10905__)
|
|
45
|
+
* __@sapirbaruch__ (__#10891__)
|
|
46
|
+
* __@nezukoagent__ (__#10901__)
|
|
47
|
+
* __@devareddy05__ (__#10929__)
|
|
48
|
+
* __@Mohammad-Faiz-Cloud-Engineer__ (__#10922__)
|
|
49
|
+
* __@azandabot__ (__#10931__)
|
|
50
|
+
* __@niksy__ (__#10896__)
|
|
51
|
+
|
|
52
|
+
[Full Changelog](https://github.com/axios/axios/compare/v1.16.1...v1.17.0)
|
|
53
|
+
|
|
3
54
|
## v1.16.1 — May 13, 2026
|
|
4
55
|
|
|
5
56
|
This release ships a defence-in-depth fix for prototype pollution in `formDataToJSON`, hardens proxy and CI workflows, restores Webpack 4 compatibility for the fetch adapter, and includes several small bug fixes and maintenance improvements.
|
|
@@ -1432,7 +1483,7 @@ This functionality is considered as a fix.
|
|
|
1432
1483
|
|
|
1433
1484
|
- fix: improve AxiosHeaders class [#5224](https://github.com/axios/axios/pull/5224)
|
|
1434
1485
|
- fix: TypeScript type definitions for commonjs [#5196](https://github.com/axios/axios/pull/5196)
|
|
1435
|
-
- fix: type definition of use method on AxiosInterceptorManager to match the
|
|
1486
|
+
- fix: type definition of use method on AxiosInterceptorManager to match the README [#5071](https://github.com/axios/axios/pull/5071)
|
|
1436
1487
|
- fix: \_\_dirname is not defined in the sandbox [#5269](https://github.com/axios/axios/pull/5269)
|
|
1437
1488
|
- fix: AxiosError.toJSON method to avoid circular references [#5247](https://github.com/axios/axios/pull/5247)
|
|
1438
1489
|
- fix: Z_BUF_ERROR when content-encoding is set but the response body is empty [#5250](https://github.com/axios/axios/pull/5250)
|
|
@@ -773,6 +773,7 @@ These config options are available for requests. Only `url` is required. Request
|
|
|
773
773
|
// When no `transformRequest` is set, it must be of one of the following types:
|
|
774
774
|
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
|
|
775
775
|
// - Browser only: FormData, File, Blob
|
|
776
|
+
// - React Native: FormData
|
|
776
777
|
// - Node only: Stream, Buffer, FormData (form-data package)
|
|
777
778
|
data: {
|
|
778
779
|
firstName: 'Fred'
|
|
@@ -877,10 +878,12 @@ These config options are available for requests. Only `url` is required. Request
|
|
|
877
878
|
// Do whatever you want with the Axios progress event
|
|
878
879
|
},
|
|
879
880
|
|
|
880
|
-
// `maxContentLength` defines the max size of the
|
|
881
|
+
// `maxContentLength` defines the max size of the response content in bytes.
|
|
882
|
+
// It is enforced by the Node.js HTTP adapter and the fetch adapter.
|
|
881
883
|
maxContentLength: 2000,
|
|
882
884
|
|
|
883
|
-
// `maxBodyLength`
|
|
885
|
+
// `maxBodyLength` defines the max size of the request content in bytes.
|
|
886
|
+
// It is enforced by the Node.js HTTP adapter and the fetch adapter when the body length can be determined.
|
|
884
887
|
maxBodyLength: 2000,
|
|
885
888
|
|
|
886
889
|
// `redact` masks matching config keys when AxiosError#toJSON() is called.
|
|
@@ -898,6 +901,12 @@ These config options are available for requests. Only `url` is required. Request
|
|
|
898
901
|
// If set to 0, Axios follows no redirects.
|
|
899
902
|
maxRedirects: 21, // default
|
|
900
903
|
|
|
904
|
+
// `sensitiveHeaders` (Node only option) lists custom secret-bearing headers
|
|
905
|
+
// to remove from cross-origin redirects. Matching is case-insensitive.
|
|
906
|
+
// Same-origin redirects keep these headers. If `maxRedirects` is 0, this
|
|
907
|
+
// option is not used.
|
|
908
|
+
sensitiveHeaders: ['X-API-Key'],
|
|
909
|
+
|
|
901
910
|
// `beforeRedirect` defines a function that Axios calls before redirect.
|
|
902
911
|
// Use this to adjust the request options upon redirecting,
|
|
903
912
|
// to inspect the latest response headers,
|
|
@@ -1640,6 +1649,7 @@ server = app.listen(3000);
|
|
|
1640
1649
|
|
|
1641
1650
|
To send data as `multipart/form-data`, pass a FormData instance as the payload.
|
|
1642
1651
|
You do not need to set the `Content-Type` header. Axios detects it from the payload type.
|
|
1652
|
+
For browser, web worker, and React Native `FormData`, leave `Content-Type` unset so the runtime can add the multipart boundary.
|
|
1643
1653
|
|
|
1644
1654
|
```js
|
|
1645
1655
|
const formData = new FormData();
|
|
@@ -2068,6 +2078,8 @@ The `rewrite` argument controls the overwriting behavior:
|
|
|
2068
2078
|
|
|
2069
2079
|
The option can also accept a user-defined function that determines whether to overwrite the value.
|
|
2070
2080
|
|
|
2081
|
+
Empty or whitespace-only header names are ignored.
|
|
2082
|
+
|
|
2071
2083
|
Returns `this`.
|
|
2072
2084
|
|
|
2073
2085
|
### AxiosHeaders#get(header)
|
|
@@ -2243,6 +2255,8 @@ const { data } = fetchAxios.get(url);
|
|
|
2243
2255
|
The adapter supports the same features as the `xhr` adapter, including upload and download progress capturing.
|
|
2244
2256
|
It also supports response types such as `stream` and `formdata` when the environment supports them.
|
|
2245
2257
|
|
|
2258
|
+
When `auth` is omitted, the fetch adapter can read HTTP Basic auth credentials from the request URL, for example `https://user:pass@example.com`. Percent-encoded URL credentials are decoded before the `Authorization` header is generated, and `auth` takes precedence over URL-embedded credentials.
|
|
2259
|
+
|
|
2246
2260
|
### Custom fetch
|
|
2247
2261
|
|
|
2248
2262
|
Since `v1.12.0`, you can configure the fetch adapter to use a custom fetch API instead of environment globals.
|
|
@@ -2365,6 +2379,20 @@ try {
|
|
|
2365
2379
|
}
|
|
2366
2380
|
```
|
|
2367
2381
|
|
|
2382
|
+
Use `axios.isCancel<T>()` to narrow cancellation errors to `CanceledError<T>`:
|
|
2383
|
+
|
|
2384
|
+
```typescript
|
|
2385
|
+
const controller = new AbortController();
|
|
2386
|
+
|
|
2387
|
+
try {
|
|
2388
|
+
await axios.get<User>('/user?ID=12345', { signal: controller.signal });
|
|
2389
|
+
} catch (error) {
|
|
2390
|
+
if (axios.isCancel<User>(error)) {
|
|
2391
|
+
handleCancellation(error);
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
```
|
|
2395
|
+
|
|
2368
2396
|
Because axios publishes an ESM default export and a CJS `module.exports`, TypeScript has a few caveats.
|
|
2369
2397
|
The recommended setting is `"moduleResolution": "node16"`, which is implied by `"module": "node16"`. This requires TypeScript 4.7 or greater.
|
|
2370
2398
|
If you use ESM, your settings should be fine.
|