Comparing version 2.0.0 to 2.0.1
@@ -5,9 +5,5 @@ 'use strict' | ||
const Benchmark = require('benchmark') | ||
const undici = require('..') | ||
const { Client } = require('..') | ||
// # Start the h2o server (in h2o repository) | ||
// # Then change the port below to 8080 | ||
// h2o -c examples/h2o/h2o.conf | ||
// | ||
// # Alternatively start the Node.js server | ||
// # Start the Node.js server | ||
// node benchmarks/server.js | ||
@@ -21,8 +17,8 @@ // | ||
hostname: 'localhost', | ||
socketPath: '/var/tmp/undici.sock', | ||
method: 'GET', | ||
path: '/', | ||
port: 3009, | ||
agent: new http.Agent({ | ||
keepAlive: true, | ||
maxSockets: 100 | ||
maxSockets: 1 | ||
}) | ||
@@ -37,7 +33,11 @@ } | ||
const pool = undici(`http://${httpOptions.hostname}:${httpOptions.port}`, { | ||
connections: 100, | ||
pipelining: 10 | ||
const client = new Client(`http://${httpOptions.hostname}`, { | ||
pipelining: 10, | ||
socketPath: '/var/tmp/undici.sock' | ||
}) | ||
client.on('disconnect', (err) => { | ||
throw err | ||
}) | ||
const suite = new Benchmark.Suite() | ||
@@ -51,14 +51,13 @@ | ||
fn: deferred => { | ||
http.get(httpOptions, response => { | ||
const stream = new Writable({ | ||
write (chunk, encoding, callback) { | ||
callback() | ||
} | ||
Promise.all(Array.from(Array(10)).map(() => new Promise((resolve) => { | ||
http.get(httpOptions, (res) => { | ||
res | ||
.pipe(new Writable({ | ||
write (chunk, encoding, callback) { | ||
callback() | ||
} | ||
})) | ||
.on('close', resolve) | ||
}) | ||
stream.once('finish', () => { | ||
deferred.resolve() | ||
}) | ||
response.pipe(stream) | ||
}) | ||
}))).then(() => deferred.resolve()) | ||
} | ||
@@ -69,15 +68,15 @@ }) | ||
fn: deferred => { | ||
pool | ||
.pipeline(undiciOptions, data => { | ||
return data.body | ||
}) | ||
.end() | ||
.pipe(new Writable({ | ||
write (chunk, encoding, callback) { | ||
callback() | ||
} | ||
})) | ||
.once('finish', () => { | ||
deferred.resolve() | ||
}) | ||
Promise.all(Array.from(Array(10)).map(() => new Promise((resolve) => { | ||
client | ||
.pipeline(undiciOptions, data => { | ||
return data.body | ||
}) | ||
.end() | ||
.pipe(new Writable({ | ||
write (chunk, encoding, callback) { | ||
callback() | ||
} | ||
})) | ||
.on('close', resolve) | ||
}))).then(() => deferred.resolve()) | ||
} | ||
@@ -88,18 +87,15 @@ }) | ||
fn: deferred => { | ||
pool.request(undiciOptions, (error, { body }) => { | ||
if (error) { | ||
throw error | ||
} | ||
const stream = new Writable({ | ||
write (chunk, encoding, callback) { | ||
callback() | ||
} | ||
}) | ||
stream.once('finish', () => { | ||
deferred.resolve() | ||
}) | ||
body.pipe(stream) | ||
}) | ||
Promise.all(Array.from(Array(10)).map(() => new Promise((resolve) => { | ||
client | ||
.request(undiciOptions) | ||
.then(({ body }) => { | ||
body | ||
.pipe(new Writable({ | ||
write (chunk, encoding, callback) { | ||
callback() | ||
} | ||
})) | ||
.on('close', resolve) | ||
}) | ||
}))).then(() => deferred.resolve()) | ||
} | ||
@@ -110,18 +106,11 @@ }) | ||
fn: deferred => { | ||
pool.stream(undiciOptions, () => { | ||
const stream = new Writable({ | ||
write (chunk, encoding, callback) { | ||
callback() | ||
} | ||
Promise.all(Array.from(Array(10)).map(() => { | ||
return client.stream(undiciOptions, () => { | ||
return new Writable({ | ||
write (chunk, encoding, callback) { | ||
callback() | ||
} | ||
}) | ||
}) | ||
stream.once('finish', () => { | ||
deferred.resolve() | ||
}) | ||
return stream | ||
}, error => { | ||
if (error) { | ||
throw error | ||
} | ||
}) | ||
})).then(() => deferred.resolve()) | ||
} | ||
@@ -132,11 +121,5 @@ }) | ||
fn: deferred => { | ||
const stream = new Writable({ | ||
write (chunk, encoding, callback) { | ||
callback() | ||
} | ||
}) | ||
stream.once('finish', () => { | ||
deferred.resolve() | ||
}) | ||
pool.dispatch(undiciOptions, new SimpleRequest(stream)) | ||
Promise.all(Array.from(Array(10)).map(() => new Promise((resolve) => { | ||
client.dispatch(undiciOptions, new SimpleRequest(resolve)) | ||
}))).then(() => deferred.resolve()) | ||
} | ||
@@ -147,13 +130,21 @@ }) | ||
fn: deferred => { | ||
pool.dispatch(undiciOptions, new NoopRequest(deferred)) | ||
Promise.all(Array.from(Array(10)).map(() => new Promise((resolve) => { | ||
client.dispatch(undiciOptions, new NoopRequest(resolve)) | ||
}))).then(() => deferred.resolve()) | ||
} | ||
}) | ||
.on('cycle', event => { | ||
console.log(String(event.target)) | ||
.on('cycle', ({ target }) => { | ||
// Multiply results by 10x to get opts/sec since we do 10 requests | ||
// per run. | ||
target.hz *= 10 | ||
console.log(String(target)) | ||
}) | ||
.on('complete', () => { | ||
client.destroy() | ||
}) | ||
.run() | ||
class NoopRequest { | ||
constructor (deferred) { | ||
this.deferred = deferred | ||
constructor (resolve) { | ||
this.resolve = resolve | ||
} | ||
@@ -174,9 +165,17 @@ | ||
onComplete (trailers) { | ||
this.deferred.resolve() | ||
this.resolve() | ||
} | ||
onError (err) { | ||
throw err | ||
} | ||
} | ||
class SimpleRequest { | ||
constructor (dst) { | ||
this.dst = dst | ||
constructor (resolve) { | ||
this.dst = new Writable({ | ||
write (chunk, encoding, callback) { | ||
callback() | ||
} | ||
}).on('close', resolve) | ||
} | ||
@@ -198,2 +197,6 @@ | ||
} | ||
onError (err) { | ||
throw err | ||
} | ||
} |
@@ -7,2 +7,2 @@ 'use strict' | ||
res.end('hello world') | ||
}).listen(3009) | ||
}).listen('/var/tmp/undici.sock') |
'use strict' | ||
const { | ||
InvalidArgumentError, | ||
RequestAbortedError | ||
} = require('./core/errors') | ||
const { InvalidArgumentError } = require('./core/errors') | ||
const { AsyncResource } = require('async_hooks') | ||
const util = require('./core/util') | ||
const { addSignal, removeSignal } = require('./abort-signal') | ||
@@ -28,11 +26,3 @@ class ConnectHandler extends AsyncResource { | ||
if (signal) { | ||
util.addListener(signal, () => { | ||
if (this.abort) { | ||
this.abort() | ||
} else { | ||
this.onError(new RequestAbortedError()) | ||
} | ||
}) | ||
} | ||
addSignal(this, signal) | ||
} | ||
@@ -51,2 +41,4 @@ | ||
removeSignal(this) | ||
this.callback = null | ||
@@ -64,2 +56,4 @@ this.runInAsyncScope(callback, null, null, { | ||
removeSignal(this) | ||
if (callback) { | ||
@@ -66,0 +60,0 @@ this.callback = null |
@@ -16,2 +16,3 @@ 'use strict' | ||
const { assert } = require('console') | ||
const { addSignal, removeSignal } = require('./abort-signal') | ||
@@ -90,7 +91,3 @@ const kResume = Symbol('resume') | ||
if (signal) { | ||
util.addListener(signal, () => { | ||
util.destroy(this.ret, new RequestAbortedError()) | ||
}) | ||
} | ||
addSignal(this, signal) | ||
@@ -133,2 +130,4 @@ this.req = new PipelineRequest().on('error', util.nop) | ||
removeSignal(this) | ||
callback(err) | ||
@@ -135,0 +134,0 @@ } |
@@ -10,2 +10,3 @@ 'use strict' | ||
const { AsyncResource } = require('async_hooks') | ||
const { addSignal, removeSignal } = require('./abort-signal') | ||
@@ -74,11 +75,3 @@ const kAbort = Symbol('abort') | ||
if (signal) { | ||
util.addListener(signal, () => { | ||
if (this.abort) { | ||
this.abort() | ||
} else { | ||
this.onError(new RequestAbortedError()) | ||
} | ||
}) | ||
} | ||
addSignal(this, signal) | ||
} | ||
@@ -121,2 +114,5 @@ | ||
const { res } = this | ||
removeSignal(this) | ||
res.push(null) | ||
@@ -128,2 +124,4 @@ } | ||
removeSignal(this) | ||
if (callback) { | ||
@@ -130,0 +128,0 @@ this.callback = null |
@@ -6,7 +6,7 @@ 'use strict' | ||
InvalidArgumentError, | ||
InvalidReturnValueError, | ||
RequestAbortedError | ||
InvalidReturnValueError | ||
} = require('./core/errors') | ||
const util = require('./core/util') | ||
const { AsyncResource } = require('async_hooks') | ||
const { addSignal, removeSignal } = require('./abort-signal') | ||
@@ -60,11 +60,3 @@ class StreamHandler extends AsyncResource { | ||
if (signal) { | ||
util.addListener(signal, () => { | ||
if (this.abort) { | ||
this.abort() | ||
} else { | ||
this.onError(new RequestAbortedError()) | ||
} | ||
}) | ||
} | ||
addSignal(this, signal) | ||
} | ||
@@ -126,2 +118,3 @@ | ||
const { res } = this | ||
return res.write(chunk) | ||
@@ -133,2 +126,4 @@ } | ||
removeSignal(this) | ||
this.trailers = trailers ? util.parseHeaders(trailers) : {} | ||
@@ -142,2 +137,4 @@ | ||
removeSignal(this) | ||
this.factory = null | ||
@@ -144,0 +141,0 @@ |
'use strict' | ||
const { | ||
InvalidArgumentError, | ||
RequestAbortedError | ||
} = require('./core/errors') | ||
const { InvalidArgumentError } = require('./core/errors') | ||
const { AsyncResource } = require('async_hooks') | ||
const util = require('./core/util') | ||
const { addSignal, removeSignal } = require('./abort-signal') | ||
@@ -28,11 +26,3 @@ class UpgradeHandler extends AsyncResource { | ||
if (signal) { | ||
util.addListener(signal, () => { | ||
if (this.abort) { | ||
this.abort() | ||
} else { | ||
this.onError(new RequestAbortedError()) | ||
} | ||
}) | ||
} | ||
addSignal(this, signal) | ||
} | ||
@@ -51,2 +41,4 @@ | ||
removeSignal(this) | ||
this.callback = null | ||
@@ -63,2 +55,4 @@ this.runInAsyncScope(callback, null, null, { | ||
removeSignal(this) | ||
if (callback) { | ||
@@ -65,0 +59,0 @@ this.callback = null |
@@ -6,3 +6,3 @@ 'use strict' | ||
const tls = require('tls') | ||
const HTTPParser = require('./node/http-parser') | ||
const HTTPParser = require('../node/http-parser') | ||
const EventEmitter = require('events') | ||
@@ -1051,36 +1051,40 @@ const assert = require('assert') | ||
const onData = function (chunk) { | ||
assert(!finished) | ||
try { | ||
assert(!finished) | ||
const len = Buffer.byteLength(chunk) | ||
if (!len) { | ||
return | ||
} | ||
const len = Buffer.byteLength(chunk) | ||
if (!len) { | ||
return | ||
} | ||
// TODO: What if not ended and bytesWritten === contentLength? | ||
// We should defer writing chunks. | ||
if (contentLength !== null && bytesWritten + len > contentLength) { | ||
util.destroy(socket, new ContentLengthMismatchError()) | ||
return | ||
} | ||
// TODO: What if not ended and bytesWritten === contentLength? | ||
// We should defer writing chunks. | ||
if (contentLength !== null && bytesWritten + len > contentLength) { | ||
util.destroy(socket, new ContentLengthMismatchError()) | ||
return | ||
} | ||
if (bytesWritten === 0) { | ||
if (!expectsPayload) { | ||
client[kReset] = true | ||
if (bytesWritten === 0) { | ||
if (!expectsPayload) { | ||
client[kReset] = true | ||
} | ||
if (contentLength === null) { | ||
socket.write(`${header}transfer-encoding: chunked\r\n`, 'ascii') | ||
} else { | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'ascii') | ||
} | ||
} | ||
if (contentLength === null) { | ||
socket.write(`${header}transfer-encoding: chunked\r\n`, 'ascii') | ||
} else { | ||
socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'ascii') | ||
socket.write(`\r\n${len.toString(16)}\r\n`, 'ascii') | ||
} | ||
} | ||
if (contentLength === null) { | ||
socket.write(`\r\n${len.toString(16)}\r\n`, 'ascii') | ||
} | ||
bytesWritten += len | ||
bytesWritten += len | ||
if (!socket.write(chunk) && this.pause) { | ||
this.pause() | ||
if (!socket.write(chunk) && this.pause) { | ||
this.pause() | ||
} | ||
} catch (err) { | ||
util.destroy(this, err) | ||
} | ||
@@ -1087,0 +1091,0 @@ } |
@@ -50,2 +50,3 @@ 'use strict' | ||
const KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)s/ | ||
function parseKeepAliveTimeout (headers) { | ||
@@ -55,4 +56,4 @@ for (let n = 0; n < headers.length; n += 2) { | ||
if (key.length === 10 && key.toLowerCase() === 'keep-alive') { | ||
const timeout = parseInt(headers[n + 1].split('timeout=', 2)[1]) | ||
return timeout ? timeout * 1000 : undefined | ||
const m = headers[n + 1].match(KEEPALIVE_TIMEOUT_EXPR) | ||
return m ? parseInt(m[1]) * 1000 : null | ||
} | ||
@@ -85,12 +86,3 @@ } | ||
function addListener (ee, fn) { | ||
if ('addEventListener' in ee) { | ||
ee.addEventListener('abort', fn) | ||
} else { | ||
ee.addListener('abort', fn) | ||
} | ||
} | ||
module.exports = { | ||
addListener, | ||
nop, | ||
@@ -97,0 +89,0 @@ isStream, |
@@ -9,3 +9,3 @@ 'use strict' | ||
} = require('./core/errors') | ||
const FixedQueue = require('./core/node/fixed-queue') | ||
const FixedQueue = require('./node/fixed-queue') | ||
@@ -12,0 +12,0 @@ const kClients = Symbol('clients') |
{ | ||
"name": "undici", | ||
"version": "2.0.0", | ||
"version": "2.0.1", | ||
"description": "An HTTP/1.1 client, written from scratch for Node.js", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -23,14 +23,24 @@ # undici | ||
Machine: 2.8GHz AMD EPYC 7402P<br/> | ||
Configuration: Node v14.4, HTTP/1.1 without TLS, 100 connections, Linux 5.4.12-1-lts | ||
Node 14 | ||
``` | ||
http - keepalive x 5,882 ops/sec ±1.87% (274 runs sampled) | ||
undici - pipeline x 9,189 ops/sec ±2.02% (272 runs sampled) | ||
undici - request x 12,623 ops/sec ±0.89% (277 runs sampled) | ||
undici - stream x 14,136 ops/sec ±0.61% (280 runs sampled) | ||
undici - dispatch x 14,883 ops/sec ±0.44% (281 runs sampled) | ||
http - keepalive x 6,770 ops/sec ±7.70% (75 runs sampled) | ||
undici - pipeline x 10,627 ops/sec ±5.88% (79 runs sampled) | ||
undici - request x 10,902 ops/sec ±1.28% (85 runs sampled) | ||
undici - stream x 20,144 ops/sec ±0.84% (86 runs sampled) | ||
undici - dispatch x 20,295 ops/sec ±1.00% (83 runs sampled) | ||
``` | ||
The benchmark is a simple `hello world` [example](benchmarks/index.js). | ||
Node 15 | ||
``` | ||
http - keepalive x 10,337 ops/sec ±6.17% (71 runs sampled) | ||
undici - pipeline x 30,387 ops/sec ±1.37% (80 runs sampled) | ||
undici - request x 40,117 ops/sec ±3.25% (77 runs sampled) | ||
undici - stream x 40,543 ops/sec ±1.30% (80 runs sampled) | ||
undici - dispatch x 50,434 ops/sec ±2.08% (77 runs sampled) | ||
``` | ||
The benchmark is a simple `hello world` [example](benchmarks/index.js) using a | ||
single unix socket with pipelining. | ||
## API | ||
@@ -41,4 +51,4 @@ | ||
A basic HTTP/1.1 client, mapped on top a single TCP/TLS connection. | ||
Keepalive is enabled by default, and it cannot be turned off. | ||
A basic HTTP/1.1 client, mapped on top a single TCP/TLS connection. Pipelining is disabled | ||
by default. | ||
@@ -75,4 +85,6 @@ `url` can be a string or a [`URL`](https://nodejs.org/api/url.html#url_class_url) object. | ||
- `pipelining: Number`, the amount of concurrent requests to be sent over the | ||
single TCP/TLS connection according to | ||
[RFC7230](https://tools.ietf.org/html/rfc7230#section-6.3.2). | ||
single TCP/TLS connection according to [RFC7230](https://tools.ietf.org/html/rfc7230#section-6.3.2). | ||
Carefully consider your workload and environment before enabling concurrent requests | ||
as pipelining may reduce performance if used incorrectly. Pipelining is sensitive | ||
to network stack settings as well as head of line blocking caused by e.g. long running requests. | ||
Default: `1`. | ||
@@ -210,3 +222,3 @@ | ||
const client = new Client'http://localhost:3000') | ||
const client = new Client('http://localhost:3000') | ||
const ee = new EventEmitter() | ||
@@ -213,0 +225,0 @@ |
@@ -9,3 +9,3 @@ 'use strict' | ||
test('basic connect', (t) => { | ||
t.plan(1) | ||
t.plan(3) | ||
@@ -33,5 +33,10 @@ const server = http.createServer((c) => { | ||
const { socket } = await client.connect({ | ||
const signal = new EE() | ||
const promise = client.connect({ | ||
signal, | ||
path: '/' | ||
}) | ||
t.strictEqual(signal.listenerCount('abort'), 1) | ||
const { socket } = await promise | ||
t.strictEqual(signal.listenerCount('abort'), 0) | ||
@@ -194,3 +199,3 @@ let recvData = '' | ||
test('connect aborted', (t) => { | ||
t.plan(4) | ||
t.plan(6) | ||
@@ -222,5 +227,7 @@ const server = http.createServer((req, res) => { | ||
t.strictEqual(opaque, 'asd') | ||
t.strictEqual(signal.listenerCount('abort'), 0) | ||
t.ok(err instanceof errors.RequestAbortedError) | ||
}) | ||
t.strictEqual(client.busy, true) | ||
t.strictEqual(signal.listenerCount('abort'), 1) | ||
signal.emit('abort') | ||
@@ -227,0 +234,0 @@ |
@@ -902,1 +902,29 @@ 'use strict' | ||
}) | ||
test('invalid body chunk does not crash', (t) => { | ||
t.plan(1) | ||
const server = createServer() | ||
server.on('request', (req, res) => { | ||
res.end() | ||
}) | ||
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: '/', | ||
body: new Readable({ | ||
objectMode: true, | ||
read () { | ||
this.push({}) | ||
} | ||
}), | ||
method: 'GET' | ||
}, (err) => { | ||
t.strictEqual(err.code, 'ERR_INVALID_ARG_TYPE') | ||
}) | ||
}) | ||
}) |
@@ -16,3 +16,3 @@ 'use strict' | ||
test('pipeline get', (t) => { | ||
t.plan(14) | ||
t.plan(17) | ||
@@ -35,5 +35,7 @@ const server = createServer((req, res) => { | ||
const bufs = [] | ||
client.pipeline({ path: '/', method: 'GET' }, ({ statusCode, headers, body }) => { | ||
const signal = new EE() | ||
client.pipeline({ signal, path: '/', method: 'GET' }, ({ statusCode, headers, body }) => { | ||
t.strictEqual(statusCode, 200) | ||
t.strictEqual(headers['content-type'], 'text/plain') | ||
t.strictEqual(signal.listenerCount('abort'), 1) | ||
return body | ||
@@ -48,2 +50,6 @@ }) | ||
}) | ||
.on('close', () => { | ||
t.strictEqual(signal.listenerCount('abort'), 0) | ||
}) | ||
t.strictEqual(signal.listenerCount('abort'), 1) | ||
} | ||
@@ -50,0 +56,0 @@ |
@@ -11,3 +11,3 @@ 'use strict' | ||
test('request abort before headers', (t) => { | ||
t.plan(2) | ||
t.plan(6) | ||
@@ -32,3 +32,6 @@ const signal = new EE() | ||
t.ok(err instanceof errors.RequestAbortedError) | ||
t.strictEqual(signal.listenerCount('abort'), 0) | ||
}) | ||
t.strictEqual(signal.listenerCount('abort'), 1) | ||
client.request({ | ||
@@ -40,3 +43,5 @@ path: '/', | ||
t.ok(err instanceof errors.RequestAbortedError) | ||
t.strictEqual(signal.listenerCount('abort'), 0) | ||
}) | ||
t.strictEqual(signal.listenerCount('abort'), 2) | ||
}) | ||
@@ -43,0 +48,0 @@ }) |
@@ -10,3 +10,3 @@ 'use strict' | ||
test('stream get', (t) => { | ||
t.plan(7) | ||
t.plan(9) | ||
@@ -26,3 +26,5 @@ const server = createServer((req, res) => { | ||
const signal = new EE() | ||
client.stream({ | ||
signal, | ||
path: '/', | ||
@@ -43,4 +45,6 @@ method: 'GET', | ||
}, (err) => { | ||
t.strictEqual(signal.listenerCount('abort'), 0) | ||
t.error(err) | ||
}) | ||
t.strictEqual(signal.listenerCount('abort'), 1) | ||
}) | ||
@@ -398,3 +402,3 @@ }) | ||
test('stream factory abort', (t) => { | ||
t.plan(1) | ||
t.plan(3) | ||
@@ -419,4 +423,6 @@ const server = createServer((req, res) => { | ||
}, (err) => { | ||
t.strictEqual(signal.listenerCount('abort'), 0) | ||
t.ok(err instanceof errors.RequestAbortedError) | ||
}) | ||
t.strictEqual(signal.listenerCount('abort'), 1) | ||
}) | ||
@@ -423,0 +429,0 @@ }) |
@@ -10,3 +10,3 @@ 'use strict' | ||
test('basic upgrade', (t) => { | ||
t.plan(3) | ||
t.plan(5) | ||
@@ -33,3 +33,5 @@ const server = net.createServer((c) => { | ||
const signal = new EE() | ||
client.upgrade({ | ||
signal, | ||
path: '/', | ||
@@ -41,2 +43,4 @@ method: 'GET', | ||
t.strictEqual(signal.listenerCount('abort'), 0) | ||
const { headers, socket } = data | ||
@@ -60,2 +64,3 @@ | ||
}) | ||
t.strictEqual(signal.listenerCount('abort'), 1) | ||
}) | ||
@@ -276,3 +281,3 @@ }) | ||
test('upgrade aborted', (t) => { | ||
t.plan(4) | ||
t.plan(6) | ||
@@ -301,4 +306,6 @@ const server = http.createServer((req, res) => { | ||
t.ok(err instanceof errors.RequestAbortedError) | ||
t.strictEqual(signal.listenerCount('abort'), 0) | ||
}) | ||
t.strictEqual(client.busy, true) | ||
t.strictEqual(signal.listenerCount('abort'), 1) | ||
signal.emit('abort') | ||
@@ -305,0 +312,0 @@ |
@@ -12,3 +12,3 @@ 'use strict' | ||
test('basic get', (t) => { | ||
t.plan(20) | ||
t.plan(23) | ||
@@ -36,3 +36,5 @@ const server = createServer((req, res) => { | ||
const signal = new EE() | ||
client.request({ | ||
signal, | ||
path: '/', | ||
@@ -45,2 +47,3 @@ method: 'GET', | ||
t.strictEqual(statusCode, 200) | ||
t.strictEqual(signal.listenerCount('abort'), 1) | ||
t.strictEqual(headers['content-type'], 'text/plain') | ||
@@ -52,5 +55,8 @@ const bufs = [] | ||
body.on('end', () => { | ||
t.strictEqual(signal.listenerCount('abort'), 0) | ||
t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) | ||
}) | ||
}) | ||
t.strictEqual(signal.listenerCount('abort'), 1) | ||
client.request({ | ||
@@ -57,0 +63,0 @@ path: '/', |
@@ -5,3 +5,3 @@ 'use strict' | ||
const FixedQueue = require('../lib/core/node/fixed-queue') | ||
const FixedQueue = require('../lib/node/fixed-queue') | ||
@@ -8,0 +8,0 @@ test('fixed queue 1', (t) => { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
338924
66
11031
660