Socket
Socket
Sign inDemoInstall

undici

Package Overview
Dependencies
Maintainers
2
Versions
211
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 2.1.1 to 2.2.0

index.d.ts

2

lib/core/client.js

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

try {
if (request.onHeaders(statusCode, headers, statusCode < 200 ? null : socket[kResume]) === false) {
if (request.onHeaders(statusCode, headers, socket[kResume]) === false) {
socket[kPause]()

@@ -558,0 +558,0 @@ }

@@ -16,2 +16,6 @@ 'use strict'

// Borrowed from https://gist.github.com/dperini/729294
// eslint-disable-next-line no-control-regex
const REGEXP_ABSOLUTE_URL = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x00a1-\xffff0-9]+-?)*[a-z\x00a1-\xffff0-9]+)(?:\.(?:[a-z\x00a1-\xffff0-9]+-?)*[a-z\x00a1-\xffff0-9]+)*(?:\.(?:[a-z\x00a1-\xffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/ius
class Request {

@@ -27,4 +31,6 @@ constructor ({

}, handler) {
if (typeof path !== 'string' || path[0] !== '/') {
throw new InvalidArgumentError('path must be a valid path')
if (typeof path !== 'string') {
throw new InvalidArgumentError('path must be a string')
} else if (path[0] !== '/' && !REGEXP_ABSOLUTE_URL.test(path)) {
throw new InvalidArgumentError('path must be an absolute URL or start with a slash')
}

@@ -31,0 +37,0 @@

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

const KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)s/
const KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/
function parseKeepAliveTimeout (val) {

@@ -54,0 +54,0 @@ const m = val.match(KEEPALIVE_TIMEOUT_EXPR)

{
"name": "undici",
"version": "2.1.1",
"version": "2.2.0",
"description": "An HTTP/1.1 client, written from scratch for Node.js",
"main": "index.js",
"types": "index.d.ts",
"module": "wrapper.mjs",
"scripts": {
"lint": "standard | snazzy",
"test": "tap test/*.js --no-coverage && jest test/jest/test",
"test": "tap test/*.{mjs,js} --no-coverage && jest test/jest/test",
"test:typescript": "tsd",
"coverage": "standard | snazzy && tap test/*.js",

@@ -32,2 +34,3 @@ "bench": "npx concurrently -k -s first \"node benchmarks/server.js\" \"node -e 'setTimeout(() => {}, 1000)' && node benchmarks\""

"@sinonjs/fake-timers": "^6.0.1",
"@types/node": "^14.6.2",
"abort-controller": "^3.0.0",

@@ -42,7 +45,14 @@ "benchmark": "^2.1.4",

"standard": "^14.3.4",
"tap": "^14.10.8"
"tap": "^14.10.8",
"tsd": "^0.13.1"
},
"pre-commit": [
"coverage"
]
],
"tsd": {
"directory": "test/types",
"compilerOptions": {
"esModuleInterop": true
}
}
}

@@ -105,3 +105,3 @@ # undici

Default: `null`.
* `signal: AbortController|EventEmitter|Null`
* `signal: AbortSignal|EventEmitter|Null`
Default: `null`.

@@ -197,6 +197,6 @@ * `requestTimeout: Number`, the timeout after which a request will time out, in

A request can may be aborted using either an `AbortController` or an `EventEmitter`.
To use `AbortController`, you will need to `npm i abort-controller`.
To use `AbortController` in Node.js versions earlier than 15, you will need to
install a shim - `npm i abort-controller`.
```js
const { AbortController } = require('abort-controller')
const { Client } = require('undici')

@@ -390,3 +390,3 @@

Default: `null`
* `signal: AbortController|EventEmitter|Null`.
* `signal: AbortSignal|EventEmitter|Null`.
Default: `null`

@@ -419,3 +419,3 @@ * `requestTimeout: Number`, the timeout after which a request will time out, in

Default: `null`
* `signal: AbortController|EventEmitter|Null`.
* `signal: AbortSignal|EventEmitter|Null`.
Default: `null`

@@ -437,3 +437,3 @@ * `requestTimeout: Number`, the timeout after which a request will time out, in

<a name='dispatch'></a>
#### `client.dispatch(opts, handler): Promise|Void`
#### `client.dispatch(opts, handler): Void`

@@ -490,3 +490,3 @@ This is the low level API which all the preceeding APIs are implemented on top of.

Closes the client and gracefully waits fo enqueued requests to
Closes the client and gracefully waits for enqueued requests to
complete before invoking the callback.

@@ -493,0 +493,0 @@

'use strict'
const { test } = require('tap')
const { AbortController } = require('abort-controller')
const { AbortController: NPMAbortController } = require('abort-controller')
const { Client, errors } = require('..')

@@ -9,114 +9,55 @@ const { createServer } = require('http')

test('Abort before sending request (no body)', (t) => {
t.plan(3)
const controllers = [{
AbortControllerImpl: NPMAbortController,
controllerName: 'npm-abortcontroller-shim'
}]
let count = 0
const server = createServer((req, res) => {
if (count === 1) {
t.fail('The second request should never be executed')
}
count += 1
res.end('hello')
if (global.AbortController) {
controllers.push({
AbortControllerImpl: global.AbortController,
controllerName: 'native-abortcontroller'
})
t.teardown(server.close.bind(server))
}
for (const { AbortControllerImpl, controllerName } of controllers) {
test(`Abort ${controllerName} before sending request (no body)`, (t) => {
t.plan(3)
server.listen(0, () => {
const client = new Client(`http://localhost:${server.address().port}`)
const abortController = new AbortController()
t.teardown(client.destroy.bind(client))
client.request({ path: '/', method: 'GET' }, (err, response) => {
t.error(err)
const bufs = []
response.body.on('data', (buf) => {
bufs.push(buf)
})
response.body.on('end', () => {
t.strictEqual('hello', Buffer.concat(bufs).toString('utf8'))
})
let count = 0
const server = createServer((req, res) => {
if (count === 1) {
t.fail('The second request should never be executed')
}
count += 1
res.end('hello')
})
t.teardown(server.close.bind(server))
client.request({ path: '/', method: 'GET', signal: abortController.signal }, (err, response) => {
t.ok(err instanceof errors.RequestAbortedError)
})
server.listen(0, () => {
const client = new Client(`http://localhost:${server.address().port}`)
const abortController = new AbortControllerImpl()
t.teardown(client.destroy.bind(client))
abortController.abort()
})
})
client.request({ path: '/', method: 'GET' }, (err, response) => {
t.error(err)
const bufs = []
response.body.on('data', (buf) => {
bufs.push(buf)
})
response.body.on('end', () => {
t.strictEqual('hello', Buffer.concat(bufs).toString('utf8'))
})
})
test('Abort while waiting response (no body)', (t) => {
t.plan(1)
const abortController = new AbortController()
const server = createServer((req, res) => {
abortController.abort()
res.setHeader('content-type', 'text/plain')
res.end('hello world')
})
t.teardown(server.close.bind(server))
server.listen(0, () => {
const client = new Client(`http://localhost:${server.address().port}`)
t.teardown(client.destroy.bind(client))
client.request({ path: '/', method: 'GET', signal: abortController.signal }, (err, response) => {
t.ok(err instanceof errors.RequestAbortedError)
})
})
})
test('Abort while waiting response (write headers started) (no body)', (t) => {
t.plan(1)
const abortController = new AbortController()
const server = createServer((req, res) => {
res.writeHead(200, { 'content-type': 'text/plain' })
res.flushHeaders()
abortController.abort()
res.end('hello world')
})
t.teardown(server.close.bind(server))
server.listen(0, () => {
const client = new Client(`http://localhost:${server.address().port}`)
t.teardown(client.destroy.bind(client))
client.request({ path: '/', method: 'GET', signal: abortController.signal }, (err, response) => {
t.ok(err instanceof errors.RequestAbortedError)
})
})
})
test('Abort while waiting response (write headers and write body started) (no body)', (t) => {
t.plan(2)
const abortController = new AbortController()
const server = createServer((req, res) => {
res.writeHead(200, { 'content-type': 'text/plain' })
res.write('hello')
res.end('world')
})
t.teardown(server.close.bind(server))
server.listen(0, () => {
const client = new Client(`http://localhost:${server.address().port}`)
t.teardown(client.destroy.bind(client))
client.request({ path: '/', method: 'GET', signal: abortController.signal }, (err, response) => {
t.error(err)
response.body.on('data', () => {
abortController.abort()
})
response.body.on('error', err => {
client.request({ path: '/', method: 'GET', signal: abortController.signal }, (err, response) => {
t.ok(err instanceof errors.RequestAbortedError)
})
abortController.abort()
})
})
})
function waitingWithBody (body, type) {
test(`Abort while waiting response (with body ${type})`, (t) => {
test(`Abort ${controllerName} while waiting response (no body)`, (t) => {
t.plan(1)
const abortController = new AbortController()
const abortController = new AbortControllerImpl()
const server = createServer((req, res) => {

@@ -133,3 +74,3 @@ abortController.abort()

client.request({ path: '/', method: 'POST', body, signal: abortController.signal }, (err, response) => {
client.request({ path: '/', method: 'GET', signal: abortController.signal }, (err, response) => {
t.ok(err instanceof errors.RequestAbortedError)

@@ -139,13 +80,7 @@ })

})
}
waitingWithBody('hello', 'string')
waitingWithBody(createReadStream(__filename), 'stream')
waitingWithBody(new Uint8Array([42]), 'Uint8Array')
function writeHeadersStartedWithBody (body, type) {
test(`Abort while waiting response (write headers started) (with body ${type})`, (t) => {
test(`Abort ${controllerName} while waiting response (write headers started) (no body)`, (t) => {
t.plan(1)
const abortController = new AbortController()
const abortController = new AbortControllerImpl()
const server = createServer((req, res) => {

@@ -163,3 +98,3 @@ res.writeHead(200, { 'content-type': 'text/plain' })

client.request({ path: '/', method: 'POST', body, signal: abortController.signal }, (err, response) => {
client.request({ path: '/', method: 'GET', signal: abortController.signal }, (err, response) => {
t.ok(err instanceof errors.RequestAbortedError)

@@ -169,13 +104,7 @@ })

})
}
writeHeadersStartedWithBody('hello', 'string')
writeHeadersStartedWithBody(createReadStream(__filename), 'stream')
writeHeadersStartedWithBody(new Uint8Array([42]), 'Uint8Array')
function writeBodyStartedWithBody (body, type) {
test(`Abort while waiting response (write headers and write body started) (with body ${type})`, (t) => {
test(`Abort ${controllerName} while waiting response (write headers and write body started) (no body)`, (t) => {
t.plan(2)
const abortController = new AbortController()
const abortController = new AbortControllerImpl()
const server = createServer((req, res) => {

@@ -192,3 +121,3 @@ res.writeHead(200, { 'content-type': 'text/plain' })

client.request({ path: '/', method: 'POST', body, signal: abortController.signal }, (err, response) => {
client.request({ path: '/', method: 'GET', signal: abortController.signal }, (err, response) => {
t.error(err)

@@ -204,6 +133,90 @@ response.body.on('data', () => {

})
function waitingWithBody (body, type) { // eslint-disable-line
test(`Abort ${controllerName} while waiting response (with body ${type})`, (t) => {
t.plan(1)
const abortController = new AbortControllerImpl()
const server = createServer((req, res) => {
abortController.abort()
res.setHeader('content-type', 'text/plain')
res.end('hello world')
})
t.teardown(server.close.bind(server))
server.listen(0, () => {
const client = new Client(`http://localhost:${server.address().port}`)
t.teardown(client.destroy.bind(client))
client.request({ path: '/', method: 'POST', body, signal: abortController.signal }, (err, response) => {
t.ok(err instanceof errors.RequestAbortedError)
})
})
})
}
waitingWithBody('hello', 'string')
waitingWithBody(createReadStream(__filename), 'stream')
waitingWithBody(new Uint8Array([42]), 'Uint8Array')
function writeHeadersStartedWithBody (body, type) { // eslint-disable-line
test(`Abort ${controllerName} while waiting response (write headers started) (with body ${type})`, (t) => {
t.plan(1)
const abortController = new AbortControllerImpl()
const server = createServer((req, res) => {
res.writeHead(200, { 'content-type': 'text/plain' })
res.flushHeaders()
abortController.abort()
res.end('hello world')
})
t.teardown(server.close.bind(server))
server.listen(0, () => {
const client = new Client(`http://localhost:${server.address().port}`)
t.teardown(client.destroy.bind(client))
client.request({ path: '/', method: 'POST', body, signal: abortController.signal }, (err, response) => {
t.ok(err instanceof errors.RequestAbortedError)
})
})
})
}
writeHeadersStartedWithBody('hello', 'string')
writeHeadersStartedWithBody(createReadStream(__filename), 'stream')
writeHeadersStartedWithBody(new Uint8Array([42]), 'Uint8Array')
function writeBodyStartedWithBody (body, type) { // eslint-disable-line
test(`Abort ${controllerName} while waiting response (write headers and write body started) (with body ${type})`, (t) => {
t.plan(2)
const abortController = new AbortControllerImpl()
const server = createServer((req, res) => {
res.writeHead(200, { 'content-type': 'text/plain' })
res.write('hello')
res.end('world')
})
t.teardown(server.close.bind(server))
server.listen(0, () => {
const client = new Client(`http://localhost:${server.address().port}`)
t.teardown(client.destroy.bind(client))
client.request({ path: '/', method: 'POST', body, signal: abortController.signal }, (err, response) => {
t.error(err)
response.body.on('data', () => {
abortController.abort()
})
response.body.on('error', err => {
t.ok(err instanceof errors.RequestAbortedError)
})
})
})
})
}
writeBodyStartedWithBody('hello', 'string')
writeBodyStartedWithBody(createReadStream(__filename), 'stream')
writeBodyStartedWithBody(new Uint8Array([42]), 'Uint8Array')
}
writeBodyStartedWithBody('hello', 'string')
writeBodyStartedWithBody(createReadStream(__filename), 'stream')
writeBodyStartedWithBody(new Uint8Array([42]), 'Uint8Array')

@@ -77,2 +77,36 @@ 'use strict'

test('keep-alive header no postfix', (t) => {
t.plan(2)
const server = createServer((socket) => {
socket.write('HTTP/1.1 200 OK\r\n')
socket.write('Content-Length: 0\r\n')
socket.write('Keep-Alive: timeout=2\r\n')
socket.write('Connection: keep-alive\r\n')
socket.write('\r\n\r\n')
})
t.teardown(server.close.bind(server))
server.listen(0, () => {
const client = new Client(`http://localhost:${server.address().port}`)
t.teardown(client.destroy.bind(client))
client.request({
path: '/',
method: 'GET'
}, (err, { body }) => {
t.error(err)
body.on('end', () => {
const timeout = setTimeout(() => {
t.fail()
}, 2e3)
client.on('disconnect', () => {
t.pass()
clearTimeout(timeout)
})
}).resume()
})
})
})
test('keep-alive not timeout', (t) => {

@@ -79,0 +113,0 @@ t.plan(2)

@@ -628,2 +628,28 @@ 'use strict'

test('an absolute url as path', (t) => {
t.plan(2)
const path = 'http://example.com'
const server = createServer((req, res) => {
t.strictEqual(req.url, path)
res.end()
})
t.tearDown(server.close.bind(server))
server.listen(0, () => {
const client = new Client({
hostname: 'localhost',
port: server.address().port,
protocol: 'http'
})
t.tearDown(client.close.bind(client))
client.request({ path, method: 'GET' }, (err, data) => {
t.error(err)
data.body.resume()
})
})
})
test('multiple destroy callback', (t) => {

@@ -630,0 +656,0 @@ t.plan(4)

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

t.ok(err instanceof errors.InvalidArgumentError)
t.strictEqual(err.message, 'path must be a valid path')
t.strictEqual(err.message, 'path must be a string')
})

@@ -32,3 +32,3 @@

t.ok(err instanceof errors.InvalidArgumentError)
t.strictEqual(err.message, 'path must be a valid path')
t.strictEqual(err.message, 'path must be an absolute URL or start with a slash')
})

@@ -35,0 +35,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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc