Comparing version 7.2.1 to 7.2.2
@@ -603,16 +603,21 @@ 'use strict' | ||
}, | ||
async pull (controller) { | ||
const { done, value } = await iterator.next() | ||
if (done) { | ||
queueMicrotask(() => { | ||
controller.close() | ||
controller.byobRequest?.respond(0) | ||
}) | ||
} else { | ||
const buf = Buffer.isBuffer(value) ? value : Buffer.from(value) | ||
if (buf.byteLength) { | ||
controller.enqueue(new Uint8Array(buf)) | ||
pull (controller) { | ||
async function pull () { | ||
const { done, value } = await iterator.next() | ||
if (done) { | ||
queueMicrotask(() => { | ||
controller.close() | ||
controller.byobRequest?.respond(0) | ||
}) | ||
} else { | ||
const buf = Buffer.isBuffer(value) ? value : Buffer.from(value) | ||
if (buf.byteLength) { | ||
controller.enqueue(new Uint8Array(buf)) | ||
} else { | ||
return await pull() | ||
} | ||
} | ||
} | ||
return controller.desiredSize > 0 | ||
return pull() | ||
}, | ||
@@ -619,0 +624,0 @@ async cancel () { |
@@ -35,3 +35,3 @@ 'use strict' | ||
if (ips == null && this.full) { | ||
cb(null, origin.origin) | ||
cb(null, origin) | ||
return | ||
@@ -78,5 +78,5 @@ } | ||
null, | ||
`${origin.protocol}//${ | ||
new URL(`${origin.protocol}//${ | ||
ip.family === 6 ? `[${ip.address}]` : ip.address | ||
}${port}` | ||
}${port}`) | ||
) | ||
@@ -110,5 +110,5 @@ }) | ||
null, | ||
`${origin.protocol}//${ | ||
new URL(`${origin.protocol}//${ | ||
ip.family === 6 ? `[${ip.address}]` : ip.address | ||
}${port}` | ||
}${port}`) | ||
) | ||
@@ -198,2 +198,34 @@ } | ||
pickFamily (origin, ipFamily) { | ||
const records = this.#records.get(origin.hostname)?.records | ||
if (!records) { | ||
return null | ||
} | ||
const family = records[ipFamily] | ||
if (!family) { | ||
return null | ||
} | ||
if (family.offset == null || family.offset === maxInt) { | ||
family.offset = 0 | ||
} else { | ||
family.offset++ | ||
} | ||
const position = family.offset % family.ips.length | ||
const ip = family.ips[position] ?? null | ||
if (ip == null) { | ||
return ip | ||
} | ||
if (Date.now() - ip.timestamp > ip.ttl) { // record TTL is already in ms | ||
// We delete expired records | ||
// It is possible that they have different TTL, so we manage them individually | ||
family.ips.splice(position, 1) | ||
} | ||
return ip | ||
} | ||
setRecords (origin, addresses) { | ||
@@ -235,6 +267,9 @@ const timestamp = Date.now() | ||
#controller = null | ||
#newOrigin = null | ||
#firstTry = true | ||
constructor (state, { origin, handler, dispatch }, opts) { | ||
constructor (state, { origin, handler, dispatch, newOrigin }, opts) { | ||
super(handler) | ||
this.#origin = origin | ||
this.#newOrigin = newOrigin | ||
this.#opts = { ...opts } | ||
@@ -250,17 +285,32 @@ this.#state = state | ||
if (this.#state.dualStack) { | ||
// We delete the record and retry | ||
this.#state.runLookup(this.#origin, this.#opts, (err, newOrigin) => { | ||
if (err) { | ||
super.onResponseError(controller, err) | ||
return | ||
} | ||
if (!this.#firstTry) { | ||
super.onResponseError(controller, err) | ||
return | ||
} | ||
this.#firstTry = false | ||
const dispatchOpts = { | ||
...this.#opts, | ||
origin: newOrigin | ||
} | ||
// Pick an ip address from the other family | ||
const otherFamily = this.#newOrigin.hostname[0] === '[' ? 4 : 6 | ||
const ip = this.#state.pickFamily(this.#origin, otherFamily) | ||
if (ip == null) { | ||
super.onResponseError(controller, err) | ||
return | ||
} | ||
this.#dispatch(dispatchOpts, this) | ||
}) | ||
let port | ||
if (typeof ip.port === 'number') { | ||
port = `:${ip.port}` | ||
} else if (this.#origin.port !== '') { | ||
port = `:${this.#origin.port}` | ||
} else { | ||
port = '' | ||
} | ||
const dispatchOpts = { | ||
...this.#opts, | ||
origin: `${this.#origin.protocol}//${ | ||
ip.family === 6 ? `[${ip.address}]` : ip.address | ||
}${port}` | ||
} | ||
this.#dispatch(dispatchOpts, this) | ||
return | ||
@@ -275,3 +325,4 @@ } | ||
this.#state.deleteRecords(this.#origin) | ||
// eslint-disable-next-line no-fallthrough | ||
super.onResponseError(controller, err) | ||
break | ||
default: | ||
@@ -366,7 +417,6 @@ super.onResponseError(controller, err) | ||
let dispatchOpts = null | ||
dispatchOpts = { | ||
const dispatchOpts = { | ||
...origDispatchOpts, | ||
servername: origin.hostname, // For SNI on TLS | ||
origin: newOrigin, | ||
origin: newOrigin.origin, | ||
headers: { | ||
@@ -380,3 +430,6 @@ host: origin.host, | ||
dispatchOpts, | ||
instance.getHandler({ origin, dispatch, handler }, origDispatchOpts) | ||
instance.getHandler( | ||
{ origin, dispatch, handler, newOrigin }, | ||
origDispatchOpts | ||
) | ||
) | ||
@@ -383,0 +436,0 @@ }) |
'use strict' | ||
const { uid, states, sentCloseFrameState, emptyBuffer, opcodes } = require('./constants') | ||
const { failWebsocketConnection, parseExtensions, isClosed, isClosing, isEstablished, validateCloseCodeAndReason } = require('./util') | ||
const { parseExtensions, isClosed, isClosing, isEstablished, validateCloseCodeAndReason } = require('./util') | ||
const { channels } = require('../../core/diagnostics') | ||
@@ -297,5 +297,30 @@ const { makeRequest } = require('../fetch/request') | ||
/** | ||
* @param {import('./websocket').Handler} handler | ||
* @param {number} code | ||
* @param {string|undefined} reason | ||
* @returns {void} | ||
*/ | ||
function failWebsocketConnection (handler, code, reason) { | ||
// If _The WebSocket Connection is Established_ prior to the point where | ||
// the endpoint is required to _Fail the WebSocket Connection_, the | ||
// endpoint SHOULD send a Close frame with an appropriate status code | ||
// (Section 7.4) before proceeding to _Close the WebSocket Connection_. | ||
if (isEstablished(handler.readyState)) { | ||
closeWebSocketConnection(handler, code, reason, false) | ||
} | ||
handler.controller.abort() | ||
if (handler.socket?.destroyed === false) { | ||
handler.socket.destroy() | ||
} | ||
handler.onFail(code, reason) | ||
} | ||
module.exports = { | ||
establishWebSocketConnection, | ||
failWebsocketConnection, | ||
closeWebSocketConnection | ||
} |
@@ -10,3 +10,2 @@ 'use strict' | ||
isValidOpcode, | ||
failWebsocketConnection, | ||
websocketMessageReceived, | ||
@@ -18,2 +17,3 @@ utf8Decode, | ||
} = require('./util') | ||
const { failWebsocketConnection } = require('./connection') | ||
const { WebsocketFrameSend } = require('./frame') | ||
@@ -20,0 +20,0 @@ const { PerMessageDeflate } = require('./permessage-deflate') |
@@ -6,4 +6,4 @@ 'use strict' | ||
const { webidl } = require('../../fetch/webidl') | ||
const { getURLRecord, isValidSubprotocol, isEstablished, failWebsocketConnection, utf8Decode } = require('../util') | ||
const { establishWebSocketConnection, closeWebSocketConnection } = require('../connection') | ||
const { getURLRecord, isValidSubprotocol, isEstablished, utf8Decode } = require('../util') | ||
const { establishWebSocketConnection, failWebsocketConnection, closeWebSocketConnection } = require('../connection') | ||
const { types } = require('node:util') | ||
@@ -10,0 +10,0 @@ const { channels } = require('../../../core/diagnostics') |
@@ -160,28 +160,2 @@ 'use strict' | ||
/** | ||
* @param {import('./websocket').Handler} handler | ||
* @param {number} code | ||
* @param {string|undefined} reason | ||
* @returns {void} | ||
*/ | ||
function failWebsocketConnection (handler, code, reason) { | ||
// If _The WebSocket Connection is Established_ prior to the point where | ||
// the endpoint is required to _Fail the WebSocket Connection_, the | ||
// endpoint SHOULD send a Close frame with an appropriate status code | ||
// (Section 7.4) before proceeding to _Close the WebSocket Connection_. | ||
if (isEstablished(handler.readyState)) { | ||
// avoid circular require - performance is not important here | ||
const { closeWebSocketConnection } = require('./connection') | ||
closeWebSocketConnection(handler, code, reason, false) | ||
} | ||
handler.controller.abort() | ||
if (handler.socket?.destroyed === false) { | ||
handler.socket.destroy() | ||
} | ||
handler.onFail(code, reason) | ||
} | ||
/** | ||
* @see https://datatracker.ietf.org/doc/html/rfc6455#section-5.5 | ||
@@ -354,3 +328,2 @@ * @param {number} opcode | ||
isValidStatusCode, | ||
failWebsocketConnection, | ||
websocketMessageReceived, | ||
@@ -357,0 +330,0 @@ utf8Decode, |
@@ -13,3 +13,2 @@ 'use strict' | ||
fireEvent, | ||
failWebsocketConnection, | ||
utf8Decode, | ||
@@ -19,3 +18,3 @@ toArrayBuffer, | ||
} = require('./util') | ||
const { establishWebSocketConnection, closeWebSocketConnection } = require('./connection') | ||
const { establishWebSocketConnection, closeWebSocketConnection, failWebsocketConnection } = require('./connection') | ||
const { ByteParser } = require('./receiver') | ||
@@ -22,0 +21,0 @@ const { kEnumerableProperty } = require('../../core/util') |
{ | ||
"name": "undici", | ||
"version": "7.2.1", | ||
"version": "7.2.2", | ||
"description": "An HTTP/1.1 client, written from scratch for Node.js", | ||
@@ -5,0 +5,0 @@ "homepage": "https://undici.nodejs.org", |
1297712
28122
57