Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

undici

Package Overview
Dependencies
Maintainers
2
Versions
220
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

undici - npm Package Compare versions

Comparing version 4.0.0-alpha.4 to 4.0.0-alpha.5

index.d.ts

2

docs/api/Agent.md

@@ -22,3 +22,3 @@ # Agent

* **factory** `(origin: URL, opts: Object) => Dispatcher` - Default: `(origin, opts) => new Pool(origin, opts)`
* **maxRedirections** `Integer` - Default: `0`.
* **maxRedirections** `Integer` - Default: `0`. The number of HTTP redirection to follow unless otherwise specified in `DispatchOptions`.

@@ -25,0 +25,0 @@ ## Instance Properties

@@ -204,3 +204,3 @@ # Dispatcher

* **onConnect** `(abort: () => void) => 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.
* **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.
* **onError** `(error: Error) => void` - Invoked when an error has occurred.

@@ -331,2 +331,3 @@ * **onUpgrade** `(statusCode: number, headers: Buffer[] | null, socket: Duplex) => void` (optional) - Invoked when request is upgraded. Required if `DispatchOptions.upgrade` is defined or `DispatchOptions.method === 'CONNECT'`.

* **body** `stream.Readable`
* **context** `object`

@@ -424,2 +425,3 @@ #### Example 1 - Pipeline Echo

* **opaque** `unknown`
* **context** `object`

@@ -573,2 +575,3 @@ #### Example 1 - Basic GET Request

* **trailers** `Record<string, string>`
* **context** `object`

@@ -751,2 +754,13 @@ #### Example 1 - Basic GET stream request

### Event: `'connectionError'`
Parameters:
* **origin** `URL`
* **targets** `Array<Dispatcher>`
* **error** `Error`
Emitted when dispatcher fails to connect to
origin.
### Event: `'drain'`

@@ -753,0 +767,0 @@

@@ -10,13 +10,13 @@ # Errors

| Error | Error Codes | Description |
| -----------------------------|-----------------------------------|------------------------------------------------|
| `InvalidArgumentError` | `UND_ERR_INVALID_ARG` | passed an invalid argument. |
| `InvalidReturnValueError` | `UND_ERR_INVALID_RETURN_VALUE` | returned an invalid value. |
| `RequestAbortedError` | `UND_ERR_ABORTED` | the request has been aborted by the user |
| `ClientDestroyedError` | `UND_ERR_DESTROYED` | trying to use a destroyed client. |
| `ClientClosedError` | `UND_ERR_CLOSED` | trying to use a closed client. |
| `SocketError` | `UND_ERR_SOCKET` | there is an error with the socket. |
| `NotSupportedError` | `UND_ERR_NOT_SUPPORTED` | encountered unsupported functionality. |
| `ContentLengthMismatchError` | `UND_ERR_CONTENT_LENGTH_MISMATCH`| body does not match content-length header |
| `InformationalError` | `UND_ERR_INFO` | expected error with reason |
| `TrailerMismatchError` | `UND_ERR_TRAILER_MISMATCH` | trailers did not match specification |
| Error | Error Codes | Description |
| ------------------------------------|---------------------------------------|---------------------------------------------------|
| `InvalidArgumentError` | `UND_ERR_INVALID_ARG` | passed an invalid argument. |
| `InvalidReturnValueError` | `UND_ERR_INVALID_RETURN_VALUE` | returned an invalid value. |
| `RequestAbortedError` | `UND_ERR_ABORTED` | the request has been aborted by the user |
| `ClientDestroyedError` | `UND_ERR_DESTROYED` | trying to use a destroyed client. |
| `ClientClosedError` | `UND_ERR_CLOSED` | trying to use a closed client. |
| `SocketError` | `UND_ERR_SOCKET` | there is an error with the socket. |
| `NotSupportedError` | `UND_ERR_NOT_SUPPORTED` | encountered unsupported functionality. |
| `RequestContentLengthMismatchError` | `UND_ERR_REQ_CONTENT_LENGTH_MISMATCH`| request body does not match content-length header |
| `InformationalError` | `UND_ERR_INFO` | expected error with reason |
| `TrailerMismatchError` | `UND_ERR_TRAILER_MISMATCH` | trailers did not match specification |

@@ -158,3 +158,3 @@ 'use strict'

if (!Number.isInteger(maxRedirections) || maxRedirections < 0) {
if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) {
throw new InvalidArgumentError('maxRedirections must be a positive number')

@@ -161,0 +161,0 @@ }

@@ -29,3 +29,3 @@ 'use strict'

onConnect (abort) {
onConnect (abort, context) {
if (!this.callback) {

@@ -36,2 +36,3 @@ throw new RequestAbortedError()

this.abort = abort
this.context = context
}

@@ -44,3 +45,3 @@

onUpgrade (statusCode, headers, socket) {
const { callback, opaque } = this
const { callback, opaque, context } = this

@@ -54,3 +55,4 @@ removeSignal(this)

socket,
opaque
opaque,
context
})

@@ -57,0 +59,0 @@ }

@@ -87,2 +87,3 @@ 'use strict'

this.abort = null
this.context = null

@@ -141,3 +142,3 @@ this.req = new PipelineRequest().on('error', util.nop)

onConnect (abort) {
onConnect (abort, context) {
const { ret, res } = this

@@ -152,6 +153,7 @@

this.abort = abort
this.context = context
}
onHeaders (statusCode, headers, resume) {
const { opaque, handler } = this
const { opaque, handler, context } = this

@@ -171,3 +173,4 @@ if (statusCode < 200) {

opaque,
body: this.res
body: this.res,
context
})

@@ -174,0 +177,0 @@ } catch (err) {

@@ -68,2 +68,3 @@ 'use strict'

this.trailers = {}
this.context = null

@@ -79,3 +80,3 @@ if (util.isStream(body)) {

onConnect (abort) {
onConnect (abort, context) {
if (!this.callback) {

@@ -86,6 +87,7 @@ throw new RequestAbortedError()

this.abort = abort
this.context = context
}
onHeaders (statusCode, headers, resume) {
const { callback, opaque, abort } = this
const { callback, opaque, abort, context } = this

@@ -106,3 +108,4 @@ if (statusCode < 200) {

opaque,
body
body,
context
})

@@ -109,0 +112,0 @@ }

@@ -51,2 +51,3 @@ 'use strict'

this.abort = null
this.context = null
this.trailers = null

@@ -64,3 +65,3 @@ this.body = body

onConnect (abort) {
onConnect (abort, context) {
if (!this.callback) {

@@ -71,6 +72,7 @@ throw new RequestAbortedError()

this.abort = abort
this.context = context
}
onHeaders (statusCode, headers, resume) {
const { factory, opaque } = this
const { factory, opaque, context } = this

@@ -85,3 +87,4 @@ if (statusCode < 200) {

headers: util.parseHeaders(headers),
opaque
opaque,
context
})

@@ -88,0 +91,0 @@

@@ -26,2 +26,3 @@ 'use strict'

this.abort = null
this.context = null

@@ -31,3 +32,3 @@ addSignal(this, signal)

onConnect (abort) {
onConnect (abort, context) {
if (!this.callback) {

@@ -38,2 +39,3 @@ throw new RequestAbortedError()

this.abort = abort
this.context = null
}

@@ -46,3 +48,3 @@

onUpgrade (statusCode, headers, socket) {
const { callback, opaque } = this
const { callback, opaque, context } = this

@@ -57,3 +59,4 @@ assert.strictEqual(statusCode, 101)

socket,
opaque
opaque,
context
})

@@ -60,0 +63,0 @@ }

@@ -12,3 +12,3 @@ 'use strict'

const {
ContentLengthMismatchError,
RequestContentLengthMismatchError,
TrailerMismatchError,

@@ -27,10 +27,2 @@ InvalidArgumentError,

const { resolve } = require('path')
const { readFileSync } = require('fs')
const constants = require('./llhttp/constants')
const WASM_BUILD = resolve(__dirname, './llhttp/llhttp.wasm')
const EMPTY_BUF = Buffer.alloc(0)
const bin = readFileSync(WASM_BUILD)
const mod = new WebAssembly.Module(bin)
const {

@@ -51,3 +43,5 @@ kUrl,

kConnected,
kConnecting,
kNeedDrain,
kNoRef,
kTLSServerName,

@@ -231,13 +225,3 @@ kTLSSession,

get [kConnected] () {
return (
this[kSocket] &&
!this[kSocket].pending &&
// Older versions of Node don't set secureConnecting to false.
(this[kSocket].authorized !== false ||
this[kSocket].authorizationError
) &&
!this[kSocket].destroyed
)
? 1
: 0
return this[kSocket] && !this[kSocket][kConnecting] && !this[kSocket].destroyed ? 1 : 0
}

@@ -365,3 +349,5 @@

for (const request of this[kQueue].splice(this[kPendingIdx])) {
const requests = this[kQueue].splice(this[kPendingIdx])
for (let i = 0; i < requests.length; i++) {
const request = requests[i]
request.onError(err)

@@ -378,4 +364,4 @@ assert(request.aborted)

this[kOnDestroyed] = null
for (const callback of callbacks) {
callback(null, null)
for (let i = 0; i < callbacks.length; i++) {
callbacks[i](null, null)
}

@@ -404,3 +390,22 @@ }

let currentParser = null
let mod, build
const { resolve } = require('path')
const { readFileSync } = require('fs')
const constants = require('./llhttp/constants')
const EMPTY_BUF = Buffer.alloc(0)
try {
build = resolve(__dirname, './llhttp/llhttp_simd.wasm')
const bin = readFileSync(build)
mod = new WebAssembly.Module(bin)
} catch (e) {
// We could check if the error was caused by the simd option not
// being enabled, but the occurring of this other error
// * https://github.com/emscripten-core/emscripten/issues/11495
// got me to remove that check to avoid breaking Node 12.
build = resolve(__dirname, './llhttp/llhttp.wasm')
const bin = readFileSync(build)
mod = new WebAssembly.Module(bin)
}
const llhttp = new WebAssembly.Instance(mod, {

@@ -412,11 +417,11 @@ env: {

assert.strictEqual(currentParser.ptr, p)
const start = at - currentParser.bufferPtr
const start = at - currentBufferPtr
const end = start + len
return currentParser.onHeaderField(currentParser.bufferRef.slice(start, end)) || 0
return currentParser.onHeaderField(currentBufferRef.slice(start, end)) || 0
},
wasm_on_header_value: (p, at, len) => {
assert.strictEqual(currentParser.ptr, p)
const start = at - currentParser.bufferPtr
const start = at - currentBufferPtr
const end = start + len
return currentParser.onHeaderValue(currentParser.bufferRef.slice(start, end)) || 0
return currentParser.onHeaderValue(currentBufferRef.slice(start, end)) || 0
},

@@ -429,5 +434,5 @@ wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => {

assert.strictEqual(currentParser.ptr, p)
const start = at - currentParser.bufferPtr
const start = at - currentBufferPtr
const end = start + len
return currentParser.onBody(currentParser.bufferRef.slice(start, end)) || 0
return currentParser.onBody(currentBufferRef.slice(start, end)) || 0
},

@@ -443,2 +448,8 @@ wasm_on_message_complete: (p) => {

let currentParser = null
let currentBufferRef = null
let currentBufferSize = 16384
let currentBufferPtr = llhttp.exports.malloc(currentBufferSize)
let currentBufferView = new Uint8Array(llhttp.exports.memory.buffer, currentBufferPtr, currentBufferSize)
const TIMEOUT_HEADERS = 1

@@ -454,5 +465,2 @@ const TIMEOUT_BODY = 2

this.ptr = llhttp.exports.llhttp_alloc(constants.TYPE.RESPONSE)
this.bufferSize = 16384
this.bufferPtr = llhttp.exports.malloc(this.bufferSize)
this.bufferRef = null
this.client = client

@@ -477,3 +485,11 @@ this.socket = socket

clearTimeout(this.timeout)
this.timeout = value ? setTimeout(onParserTimeout, value, this) : null
if (value) {
this.timeout = setTimeout(onParserTimeout, value, this)
// istanbul ignore else: only for jest
if (this.timeout.unref) {
this.timeout.unref()
}
} else {
this.timeout = null
}
this.timeoutValue = value

@@ -518,13 +534,11 @@ } else if (this.timeout) {

// Be sure the parser buffer can contain `data`
if (data.length > this.bufferSize) {
llhttp.exports.free(this.bufferPtr)
this.bufferSize = Math.ceil(data.length / 4096) * 4096
this.bufferPtr = llhttp.exports.malloc(this.bufferSize)
if (data.length > currentBufferSize) {
llhttp.exports.free(currentBufferPtr)
currentBufferSize = Math.ceil(data.length / 4096) * 4096
currentBufferPtr = llhttp.exports.malloc(currentBufferSize)
currentBufferView = new Uint8Array(llhttp.exports.memory.buffer, currentBufferPtr, currentBufferSize)
}
assert(this.bufferSize >= data.length)
// TODO (perf): Can we avoid this copy somehow?
new Uint8Array(llhttp.exports.memory.buffer, this.bufferPtr, this.bufferSize).set(data)
currentBufferView.set(data)

@@ -535,13 +549,13 @@ // Call `execute` on the wasm parser.

// The return value is an error code or `constants.ERROR.OK`.
this.bufferRef = data
currentBufferRef = data
currentParser = this
const ret = llhttp.exports.llhttp_execute(this.ptr, this.bufferPtr, data.length)
const ret = llhttp.exports.llhttp_execute(this.ptr, currentBufferPtr, data.length)
currentParser = null
this.bufferRef = null
currentBufferRef = null
if (ret === constants.ERROR.PAUSED_UPGRADE) {
const offset = llhttp.exports.llhttp_get_error_pos(this.ptr) - this.bufferPtr
const offset = llhttp.exports.llhttp_get_error_pos(this.ptr) - currentBufferPtr
this.onUpgrade(data.slice(offset))
} else if (ret === constants.ERROR.PAUSED) {
const offset = llhttp.exports.llhttp_get_error_pos(this.ptr) - this.bufferPtr
const offset = llhttp.exports.llhttp_get_error_pos(this.ptr) - currentBufferPtr
this.paused = true

@@ -563,3 +577,2 @@ socket.pause()

assert(this.ptr != null)
assert(this.bufferPtr != null)
assert(currentParser == null)

@@ -570,5 +583,2 @@

llhttp.exports.free(this.bufferPtr)
this.bufferPtr = null
clearTimeout(this.timeout)

@@ -725,4 +735,5 @@ this.timeout = null

for (let n = 0; n < rawHeaders.length; n += 2) {
const key = rawHeaders[n + 0]
let looking = true
for (let n = 0; n < rawHeaders.length && looking; n += 2) {
const key = rawHeaders[n]
const val = rawHeaders[n + 1]

@@ -732,4 +743,6 @@

keepAlive = val
looking = !trailers
} else if (!trailers && key.length === 7 && key.toString().toLowerCase() === 'trailer') {
trailers = val
looking = !keepAlive
}

@@ -835,6 +848,7 @@ }

for (const trailer of trailers) {
for (let i = 0; i < trailers.length; i++) {
const trailer = trailers[i]
let found = false
for (let n = 0; n < rawTrailers.length; n += 2) {
const key = rawTrailers[n + 0]
const key = rawTrailers[n]
if (key.length === trailer.length && key.toString().toLowerCase() === trailer.toLowerCase()) {

@@ -910,2 +924,3 @@ found = true

this[kConnecting] = false
client.emit('connect', client[kUrl], [client])

@@ -935,3 +950,6 @@ resume(client)

// socket error.
for (const request of client[kQueue].splice(client[kRunningIdx])) {
const requests = client[kQueue].splice(client[kRunningIdx])
for (let i = 0; i < requests.length; i++) {
const request = requests[i]
request.onError(err)

@@ -979,3 +997,5 @@ assert(request.aborted)

// Fail entire queue.
for (const request of client[kQueue].splice(client[kRunningIdx])) {
const requests = client[kQueue].splice(client[kRunningIdx])
for (let i = 0; i < requests.length; i++) {
const request = requests[i]
request.onError(err)

@@ -997,3 +1017,8 @@ assert(request.aborted)

client.emit('disconnect', client[kUrl], [client], err)
if (this[kConnecting]) {
this[kConnecting] = false
client.emit('connectionError', client[kUrl], [client], err)
} else {
client.emit('disconnect', client[kUrl], [client], err)
}

@@ -1047,2 +1072,4 @@ resume(client)

socket[kNoRef] = false
socket[kConnecting] = true
socket[kWriting] = false

@@ -1096,6 +1123,15 @@ socket[kReset] = false

const socket = client[kSocket]
const connected = client[kConnected]
if (socket) {
if (!connected) {
if (client[kSize] === 0) {
if (!socket[kNoRef] && socket.unref) {
socket.unref()
socket[kNoRef] = true
}
} else if (socket[kNoRef] && socket.ref) {
socket.ref()
socket[kNoRef] = false
}
if (socket[kConnecting]) {
if (socket[kParser].timeoutType !== TIMEOUT_CONNECT) {

@@ -1166,10 +1202,6 @@ socket[kParser].setTimeout(client[kConnectTimeoutValue], TIMEOUT_CONNECT)

if (!connected) {
if (socket.destroyed || socket[kConnecting] || socket[kWriting] || socket[kReset]) {
return
}
if (socket[kWriting] || socket[kReset]) {
return
}
if (client[kRunning] > 0 && !request.idempotent) {

@@ -1266,3 +1298,3 @@ // Non-idempotent request cannot be retried.

if (client[kStrictContentLength]) {
request.onError(new ContentLengthMismatchError())
request.onError(new RequestContentLengthMismatchError())
assert(request.aborted)

@@ -1272,3 +1304,3 @@ return false

process.emitWarning(new ContentLengthMismatchError())
process.emitWarning(new RequestContentLengthMismatchError())
}

@@ -1287,3 +1319,3 @@

socket.destroy(new InformationalError('aborted'))
util.destroy(socket, new InformationalError('aborted'))
})

@@ -1380,7 +1412,7 @@ } catch (err) {

if (client[kStrictContentLength]) {
util.destroy(socket, new ContentLengthMismatchError())
util.destroy(socket, new RequestContentLengthMismatchError())
return
}
process.emitWarning(new ContentLengthMismatchError())
process.emitWarning(new RequestContentLengthMismatchError())
}

@@ -1435,5 +1467,5 @@

if (client[kStrictContentLength]) {
err = new ContentLengthMismatchError()
err = new RequestContentLengthMismatchError()
} else {
process.emitWarning(new ContentLengthMismatchError())
process.emitWarning(new RequestContentLengthMismatchError())
}

@@ -1440,0 +1472,0 @@ }

@@ -91,7 +91,7 @@ 'use strict'

class ContentLengthMismatchError extends UndiciError {
class RequestContentLengthMismatchError extends UndiciError {
constructor (message) {
super(message)
Error.captureStackTrace(this, ContentLengthMismatchError)
this.name = 'ContentLengthMismatchError'
Error.captureStackTrace(this, RequestContentLengthMismatchError)
this.name = 'RequestContentLengthMismatchError'
this.message = message || 'Request body length does not match content-length header'

@@ -157,3 +157,3 @@ this.code = 'UND_ERR_CONTENT_LENGTH_MISMATCH'

BodyTimeoutError,
ContentLengthMismatchError,
RequestContentLengthMismatchError,
ConnectTimeoutError,

@@ -160,0 +160,0 @@ TrailerMismatchError,

@@ -86,7 +86,9 @@ 'use strict'

for (let i = 0; i < headers.length; i += 2) {
processHeader(this, headers[i + 0], headers[i + 1])
processHeader(this, headers[i], headers[i + 1])
}
} else if (headers && typeof headers === 'object') {
for (const [key, val] of Object.entries(headers)) {
processHeader(this, key, val)
const keys = Object.keys(headers)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
processHeader(this, key, headers[key])
}

@@ -130,3 +132,3 @@ } else if (headers != null) {

return this[kHandler].onConnect(abort)
return this[kHandler].onConnect(abort, this.context)
}

@@ -133,0 +135,0 @@

@@ -7,2 +7,3 @@ module.exports = {

kConnect: Symbol('connect'),
kConnecting: Symbol('connecting'),
kConnectTimeoutValue: Symbol('connect timeout value'),

@@ -18,2 +19,3 @@ kKeepAliveDefaultTimeout: Symbol('default keep alive timeout'),

kHost: Symbol('host'),
kNoRef: Symbol('no ref'),
kRunning: Symbol('running'),

@@ -20,0 +22,0 @@ kPending: Symbol('pending'),

@@ -6,14 +6,20 @@ 'use strict'

const redirectableStatusCodes = [300, 301, 302, 303, 307, 308]
class RedirectHandler {
constructor (agent, opts, handler) {
this.agent = agent
constructor (dispatcher, { maxRedirections, ...opts }, handler) {
this.dispatcher = dispatcher
this.location = null
this.abort = null
this.opts = opts
this.maxRedirections = maxRedirections
this.handler = handler
this.history = []
}
onConnect (abort) {
onConnect (abort, context = {}) {
context.history = this.history
this.abort = abort
this.handler.onConnect(abort)
this.handler.onConnect(abort, context)
}

@@ -30,8 +36,6 @@

onHeaders (statusCode, headers, resume) {
if ([300, 301, 302, 303, 307, 308].indexOf(statusCode) === -1) {
return this.handler.onHeaders(statusCode, headers, resume)
}
this.location = this.history.length >= this.maxRedirections
? null
: parseLocation(statusCode, headers)
this.location = parseLocation(headers)
if (!this.location) {

@@ -41,8 +45,7 @@ return this.handler.onHeaders(statusCode, headers, resume)

this.history.push(new URL(this.opts.path, this.opts.origin))
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin))
const path = search ? `${pathname}${search}` : pathname
this.opts = { ...this.opts }
this.opts.maxRedirections = this.opts.maxRedirections - 1
// Remove headers referring to the original URL.

@@ -98,3 +101,6 @@ // By default it is Host only, unless it's a 303 (see below), which removes also all Content-* headers.

this.agent.dispatch(this.opts, this.handler)
this.location = null
this.abort = null
this.dispatcher.dispatch(this.opts, this)
} else {

@@ -106,3 +112,7 @@ this.handler.onComplete(trailers)

function parseLocation (headers) {
function parseLocation (statusCode, headers) {
if (redirectableStatusCodes.indexOf(statusCode) === -1) {
return null
}
for (let i = 0; i < headers.length; i += 2) {

@@ -133,5 +143,7 @@ if (headers[i].length === 8 && headers[i].toString().toLowerCase() === 'location') {

} else if (headers && typeof headers === 'object') {
for (const [key, val] of Object.entries(headers)) {
const keys = Object.keys(headers)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
if (!shouldRemoveHeader(key, removeContent)) {
ret.push(key, val)
ret.push(key, headers[key])
}

@@ -138,0 +150,0 @@ }

{
"name": "undici",
"version": "4.0.0-alpha.4",
"version": "4.0.0-alpha.5",
"description": "An HTTP/1.1 client, written from scratch for Node.js",

@@ -25,3 +25,4 @@ "homepage": "https://undici.nodejs.org",

"files": [
"index.(js|d.ts)",
"*.d.ts",
"index.js",
"lib",

@@ -41,4 +42,7 @@ "types",

"coverage:ci": "npm run coverage -- --coverage-report=lcovonly",
"prebench": "node -e \"try { require('fs').unlinkSync(require('path').join(require('os').tmpdir(), 'undici.sock')) } catch (_) {}\"",
"bench": "npx concurrently -k -s first \"node benchmarks/server.js\" \"node -e 'setTimeout(() => {}, 1000)' && node benchmarks\"",
"bench": "concurrently -k -s first npm:bench:server npm:bench:run",
"bench:simd": "concurrently -k -s first npm:bench:server npm:bench:run:simd",
"bench:server": "node benchmarks/server.js",
"prebench:run": "node benchmarks/wait.js",
"bench:run": "CONNECTIONS=1 node --experimental-wasm-simd benchmarks/benchmark.js && CONNECTIONS=50 node --experimental-wasm-simd benchmarks/benchmark.js",
"serve:website": "docsify serve .",

@@ -51,4 +55,4 @@ "prepare": "husky install"

"abort-controller": "^3.0.0",
"benchmark": "^2.1.4",
"concurrently": "^6.0.2",
"cronometro": "^0.8.0",
"docsify-cli": "^4.4.2",

@@ -66,3 +70,4 @@ "https-pem": "^2.0.0",

"tap": "^15.0.0",
"tsd": "^0.14.0"
"tsd": "^0.14.0",
"wait-on": "^5.3.0"
},

@@ -69,0 +74,0 @@ "engines": {

@@ -20,16 +20,28 @@ # undici

Machine: AMD EPYC 7502P
The benchmark is a simple `hello world` [example](benchmarks/index.js) using a
number of unix sockets (connections) with a pipelining depth of 10 running on Node 16.
The benchmarks have the [simd](https://github.com/WebAssembly/simd) feature enabled.
Node 15
```
http - keepalive x 12,028 ops/sec ±2.60% (265 runs sampled)
undici - pipeline x 31,321 ops/sec ±0.77% (276 runs sampled)
undici - request x 36,612 ops/sec ±0.71% (277 runs sampled)
undici - stream x 41,291 ops/sec ±0.90% (268 runs sampled)
undici - dispatch x 47,319 ops/sec ±1.17% (263 runs sampled)
```
### Connections 1
The benchmark is a simple `hello world` [example](benchmarks/index.js) using a
single unix socket with pipelining.
| Tests | Samples | Result | Tolerance | Difference with slowest |
|---------------------|---------|---------------|-----------|-------------------------|
| http - no keepalive | 15 | 4.63 req/sec | ± 2.77 % | - |
| http - keepalive | 10 | 4.81 req/sec | ± 2.16 % | + 3.94 % |
| undici - stream | 25 | 62.22 req/sec | ± 2.67 % | + 1244.58 % |
| undici - dispatch | 15 | 64.33 req/sec | ± 2.47 % | + 1290.24 % |
| undici - request | 15 | 66.08 req/sec | ± 2.48 % | + 1327.88 % |
| undici - pipeline | 10 | 66.13 req/sec | ± 1.39 % | + 1329.08 % |
### Connections 50
| Tests | Samples | Result | Tolerance | Difference with slowest |
|---------------------|---------|------------------|-----------|-------------------------|
| http - no keepalive | 50 | 3546.49 req/sec | ± 2.90 % | - |
| http - keepalive | 15 | 5692.67 req/sec | ± 2.48 % | + 60.52 % |
| undici - pipeline | 25 | 8478.71 req/sec | ± 2.62 % | + 139.07 % |
| undici - request | 20 | 9766.66 req/sec | ± 2.79 % | + 175.39 % |
| undici - stream | 15 | 10109.74 req/sec | ± 2.94 % | + 185.06 % |
| undici - dispatch | 25 | 10949.73 req/sec | ± 2.54 % | + 208.75 % |
## Quick Start

@@ -73,4 +85,2 @@

`url` may contain pathname. `options` may not contain path.
Calls `options.dispatcher.request(options)`.

@@ -88,2 +98,3 @@

* **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`
* **maxRedirections** `Integer` - Default: `0`
* **factory** `Dispatcher.stream.factory`

@@ -105,2 +116,3 @@

* **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`
* **maxRedirections** `Integer` - Default: `0`
* **handler** `Dispatcher.pipeline.handler`

@@ -123,2 +135,3 @@

* **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)
* **maxRedirections** `Integer` - Default: `0`
* **callback** `(err: Error | null, data: ConnectData | null) => void` (optional)

@@ -141,2 +154,3 @@

* **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcherdispatcher)
* **maxRedirections** `Integer` - Default: `0`
* **callback** `(error: Error | null, data: UpgradeData) => void` (optional)

@@ -154,7 +168,7 @@

Sets the global dispatcher used by global API methods.
Sets the global dispatcher used by Common API Methods.
### `undici.getGlobalDispatcher()`
Gets the global dispatcher used by global API methods.
Gets the global dispatcher used by Common API Methods.

@@ -161,0 +175,0 @@ Returns: `Dispatcher`

@@ -95,2 +95,3 @@ import { URL } from 'url'

opaque: unknown;
context: object;
}

@@ -102,2 +103,3 @@ export interface PipelineHandlerData {

body: Readable;
context: object;
}

@@ -117,2 +119,3 @@ export interface StreamData {

opaque: unknown;
context: object;
}

@@ -119,0 +122,0 @@ export type StreamFactory = (data: StreamFactoryData) => Writable;

@@ -49,4 +49,4 @@ export = Errors

/** Body does not match content-length header. */
export class ContentLengthMismatchError extends UndiciError {
name: 'ContentLengthMismatchError';
export class RequestContentLengthMismatchError extends UndiciError {
name: 'RequestContentLengthMismatchError';
code: 'UND_ERR_CONTENT_LENGTH_MISMATCH';

@@ -53,0 +53,0 @@ }

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc