undici
Advanced tools
Comparing version 1.3.0 to 1.3.1
@@ -155,11 +155,11 @@ 'use strict' | ||
_onHeaders () { | ||
onHeaders () { | ||
} | ||
_onData (chunk) { | ||
onData (chunk) { | ||
return true | ||
} | ||
_onComplete (trailers) { | ||
onComplete (trailers) { | ||
this.deferred.resolve() | ||
@@ -174,13 +174,13 @@ } | ||
_onHeaders (statusCode, headers, resume) { | ||
onHeaders (statusCode, headers, resume) { | ||
this.dst.on('drain', resume) | ||
} | ||
_onData (chunk) { | ||
onData (chunk) { | ||
return this.dst.write(chunk) | ||
} | ||
_onComplete () { | ||
onComplete () { | ||
this.dst.end() | ||
} | ||
} |
@@ -13,3 +13,3 @@ 'use strict' | ||
_onUpgrade (statusCode, headers, socket) { | ||
onUpgrade (statusCode, headers, socket) { | ||
const { callback, opaque } = this | ||
@@ -26,9 +26,7 @@ | ||
_onError (err) { | ||
onError (err) { | ||
const { callback, opaque } = this | ||
if (callback) { | ||
this.callback = null | ||
callback(err, { opaque }) | ||
} | ||
this.callback = null | ||
callback(err, { opaque }) | ||
} | ||
@@ -35,0 +33,0 @@ } |
@@ -113,3 +113,3 @@ 'use strict' | ||
_onHeaders (statusCode, headers, resume) { | ||
onHeaders (statusCode, headers, resume) { | ||
const { opaque, handler, ret } = this | ||
@@ -175,3 +175,3 @@ | ||
_onData (chunk) { | ||
onData (chunk) { | ||
const { res } = this | ||
@@ -186,3 +186,3 @@ | ||
_onComplete (trailers) { | ||
onComplete (trailers) { | ||
const { res } = this | ||
@@ -197,3 +197,3 @@ | ||
_onError (err) { | ||
onError (err) { | ||
const { ret } = this | ||
@@ -200,0 +200,0 @@ |
@@ -36,3 +36,3 @@ 'use strict' | ||
_onHeaders (statusCode, headers, resume) { | ||
onHeaders (statusCode, headers, resume) { | ||
const { callback, opaque } = this | ||
@@ -57,3 +57,3 @@ | ||
_onData (chunk) { | ||
onData (chunk) { | ||
const { res } = this | ||
@@ -68,3 +68,3 @@ | ||
_onComplete (trailers) { | ||
onComplete (trailers) { | ||
const { res } = this | ||
@@ -79,3 +79,3 @@ | ||
_onError (err) { | ||
onError (err) { | ||
const { res, callback, opaque } = this | ||
@@ -82,0 +82,0 @@ |
@@ -22,3 +22,3 @@ 'use strict' | ||
_onHeaders (statusCode, headers, resume) { | ||
onHeaders (statusCode, headers, resume) { | ||
const { factory, callback, opaque } = this | ||
@@ -70,3 +70,3 @@ | ||
_onData (chunk) { | ||
onData (chunk) { | ||
const { res } = this | ||
@@ -81,3 +81,3 @@ | ||
_onComplete (trailers) { | ||
onComplete (trailers) { | ||
const { res } = this | ||
@@ -94,3 +94,3 @@ | ||
_onError (err) { | ||
onError (err) { | ||
const { res, callback, opaque } = this | ||
@@ -97,0 +97,0 @@ |
@@ -13,3 +13,3 @@ 'use strict' | ||
_onUpgrade (statusCode, headers, socket) { | ||
onUpgrade (statusCode, headers, socket) { | ||
const { callback, opaque } = this | ||
@@ -25,9 +25,7 @@ | ||
_onError (err) { | ||
onError (err) { | ||
const { callback, opaque } = this | ||
if (callback) { | ||
this.callback = null | ||
callback(err, { opaque }) | ||
} | ||
this.callback = null | ||
callback(err, { opaque }) | ||
} | ||
@@ -34,0 +32,0 @@ } |
@@ -256,12 +256,6 @@ 'use strict' | ||
/* istanbul ignore next: only used for test */ | ||
/* istanbul ignore: only used for test */ | ||
[kConnect] (cb) { | ||
connect(this) | ||
if (cb) { | ||
if (this.connected) { | ||
process.nextTick(cb) | ||
} else { | ||
this.once('connect', cb) | ||
} | ||
} | ||
this.once('connect', cb) | ||
} | ||
@@ -419,4 +413,4 @@ | ||
[HTTPParser.kOnTimeout] () { | ||
/* istanbul ignore next: https://github.com/nodejs/node/pull/34578 */ | ||
if (this.statusCode) { | ||
// https://github.com/nodejs/node/pull/34578 | ||
this.socket._unrefTimer() | ||
@@ -542,7 +536,8 @@ } else { | ||
if (statusCode === 100) { | ||
// TODO: 100 Continue | ||
} else { | ||
request.onHeaders(statusCode, headers, statusCode < 200 ? null : socket[kResume]) | ||
util.destroy(socket, new SocketError('bad response')) | ||
return | ||
} | ||
request.onHeaders(statusCode, headers, statusCode < 200 ? null : socket[kResume]) | ||
return request.method === 'HEAD' || statusCode < 200 ? 1 : 0 | ||
@@ -1027,4 +1022,5 @@ } | ||
} | ||
/* istanbul ignore next */ | ||
const onClose = function () { | ||
onFinished(new SocketError('closed')) | ||
assert(false, 'socket should not close without error') | ||
} | ||
@@ -1031,0 +1027,0 @@ const onFinished = function (err) { |
@@ -200,3 +200,3 @@ 'use strict' | ||
this[kHandler]._onUpgrade(statusCode, headers, socket) | ||
this[kHandler].onUpgrade(statusCode, headers, socket) | ||
} | ||
@@ -222,3 +222,3 @@ | ||
this[kHandler]._onHeaders(statusCode, headers, resume) | ||
this[kHandler].onHeaders(statusCode, headers, resume) | ||
} | ||
@@ -233,3 +233,3 @@ | ||
return this[kHandler]._onData(chunk.slice(offset, offset + length)) | ||
return this[kHandler].onData(chunk.slice(offset, offset + length)) | ||
} | ||
@@ -246,3 +246,3 @@ | ||
return this[kHandler]._onComplete(trailers) | ||
return this[kHandler].onComplete(trailers) | ||
} | ||
@@ -268,3 +268,3 @@ | ||
process.nextTick((handler, err) => { | ||
handler._onError(err) | ||
handler.onError(err) | ||
}, this[kHandler], err) | ||
@@ -271,0 +271,0 @@ } |
{ | ||
"name": "undici", | ||
"version": "1.3.0", | ||
"version": "1.3.1", | ||
"description": "An HTTP/1.1 client, written from scratch for Node.js", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -244,3 +244,3 @@ 'use strict' | ||
test('invalid options throws', (t) => { | ||
t.plan(30) | ||
t.plan(38) | ||
@@ -304,2 +304,38 @@ try { | ||
new Client(new URL('http://localhost:200'), { // eslint-disable-line | ||
idleTimeout: 'asd' | ||
}) // eslint-disable-line | ||
} catch (err) { | ||
t.ok(err instanceof errors.InvalidArgumentError) | ||
t.strictEqual(err.message, 'invalid idleTimeout') | ||
} | ||
try { | ||
new Client(new URL('http://localhost:200'), { // eslint-disable-line | ||
maxKeepAliveTimeout: 'asd' | ||
}) // eslint-disable-line | ||
} catch (err) { | ||
t.ok(err instanceof errors.InvalidArgumentError) | ||
t.strictEqual(err.message, 'invalid maxKeepAliveTimeout') | ||
} | ||
try { | ||
new Client(new URL('http://localhost:200'), { // eslint-disable-line | ||
maxKeepAliveTimeout: 0 | ||
}) // eslint-disable-line | ||
} catch (err) { | ||
t.ok(err instanceof errors.InvalidArgumentError) | ||
t.strictEqual(err.message, 'invalid maxKeepAliveTimeout') | ||
} | ||
try { | ||
new Client(new URL('http://localhost:200'), { // eslint-disable-line | ||
keepAliveTimeoutThreshold: 'asd' | ||
}) // eslint-disable-line | ||
} catch (err) { | ||
t.ok(err instanceof errors.InvalidArgumentError) | ||
t.strictEqual(err.message, 'invalid keepAliveTimeoutThreshold') | ||
} | ||
try { | ||
new Client(new URL('http://localhost:200'), { // eslint-disable-line | ||
socketTimeout: 'asd' | ||
@@ -306,0 +342,0 @@ }) |
@@ -25,4 +25,3 @@ 'use strict' | ||
path: '/', | ||
method: 'GET', | ||
idleTimeout: 30e3 | ||
method: 'GET' | ||
}, (err, { body }) => { | ||
@@ -42,1 +41,145 @@ t.error(err) | ||
}) | ||
test('keep-alive header 1', (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=1s\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() | ||
}, 0) | ||
client.on('disconnect', () => { | ||
t.pass() | ||
clearTimeout(timeout) | ||
}) | ||
}).resume() | ||
}) | ||
}) | ||
}) | ||
test('keep-alive not timeout', (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: timeoutasdasd=1s\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}`, { | ||
idleTimeout: 1e3 | ||
}) | ||
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 threshold', (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=30s\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}`, { | ||
idleTimeout: 30e3, | ||
keepAliveTimeoutThreshold: 29e3 | ||
}) | ||
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 max keepalive', (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=30s\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}`, { | ||
idleTimeout: 30e3, | ||
maxKeepAliveTimeout: 1e3 | ||
}) | ||
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() | ||
}) | ||
}) | ||
}) |
@@ -301,1 +301,33 @@ 'use strict' | ||
}) | ||
test('basic aborted after res', (t) => { | ||
t.plan(1) | ||
const signal = new EE() | ||
const server = http.createServer() | ||
server.on('upgrade', (req, c, head) => { | ||
c.write('HTTP/1.1 101\r\n') | ||
c.write('hello: world\r\n') | ||
c.write('connection: upgrade\r\n') | ||
c.write('upgrade: websocket\r\n') | ||
c.write('\r\n') | ||
c.write('Body') | ||
c.end() | ||
signal.emit('abort') | ||
}) | ||
t.tearDown(server.close.bind(server)) | ||
server.listen(0, () => { | ||
const client = new Client(`http://localhost:${server.address().port}`) | ||
t.tearDown(client.close.bind(client)) | ||
client.upgrade({ | ||
path: '/', | ||
method: 'GET', | ||
protocol: 'Websocket', | ||
signal | ||
}, (err) => { | ||
t.ok(err instanceof errors.RequestAbortedError) | ||
}) | ||
}) | ||
}) |
@@ -860,1 +860,30 @@ 'use strict' | ||
}) | ||
test('POST empty with error', (t) => { | ||
t.plan(1) | ||
const server = createServer((req, res) => { | ||
req.pipe(res) | ||
}) | ||
t.tearDown(server.close.bind(server)) | ||
server.listen(0, () => { | ||
const client = new Client(`http://localhost:${server.address().port}`) | ||
t.tearDown(client.close.bind(client)) | ||
const body = new Readable({ | ||
read () { | ||
} | ||
}) | ||
body.push(null) | ||
client.on('connect', () => { | ||
process.nextTick(() => { | ||
body.emit('error', new Error('asd')) | ||
}) | ||
}) | ||
client.request({ path: '/', method: 'POST', body }, (err, data) => { | ||
t.strictEqual(err.message, 'asd') | ||
}) | ||
}) | ||
}) |
@@ -62,1 +62,25 @@ 'use strict' | ||
}) | ||
test('error 100 body', (t) => { | ||
t.plan(2) | ||
const server = net.createServer((socket) => { | ||
socket.write('HTTP/1.1 100 Early Hints\r\n') | ||
socket.write('\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) => { | ||
t.strictEqual(err.message, 'bad response') | ||
}) | ||
client.on('disconnect', () => { | ||
t.pass() | ||
}) | ||
}) | ||
}) |
@@ -7,3 +7,3 @@ 'use strict' | ||
test('invalid headers', (t) => { | ||
t.plan(9) | ||
t.plan(10) | ||
@@ -36,2 +36,12 @@ const client = new Client('http://localhost:3000') | ||
headers: { | ||
upgrade: 'asd' | ||
} | ||
}, (err, data) => { | ||
t.ok(err instanceof errors.InvalidArgumentError) | ||
}) | ||
client.request({ | ||
path: '/', | ||
method: 'GET', | ||
headers: { | ||
connection: 'close' | ||
@@ -38,0 +48,0 @@ } |
120
test/pool.js
@@ -12,2 +12,3 @@ 'use strict' | ||
const eos = require('stream').finished | ||
const net = require('net') | ||
@@ -310,1 +311,120 @@ test('basic get', (t) => { | ||
}) | ||
test('pool upgrade promise', (t) => { | ||
t.plan(2) | ||
const server = net.createServer((c) => { | ||
c.on('data', (d) => { | ||
c.write('HTTP/1.1 101\r\n') | ||
c.write('hello: world\r\n') | ||
c.write('connection: upgrade\r\n') | ||
c.write('upgrade: websocket\r\n') | ||
c.write('\r\n') | ||
c.write('Body') | ||
}) | ||
c.on('end', () => { | ||
c.end() | ||
}) | ||
}) | ||
t.tearDown(server.close.bind(server)) | ||
server.listen(0, async () => { | ||
const client = new Pool(`http://localhost:${server.address().port}`) | ||
t.tearDown(client.close.bind(client)) | ||
const { headers, socket } = await client.upgrade({ | ||
path: '/', | ||
method: 'GET', | ||
protocol: 'Websocket' | ||
}) | ||
let recvData = '' | ||
socket.on('data', (d) => { | ||
recvData += d | ||
}) | ||
socket.on('close', () => { | ||
t.strictEqual(recvData.toString(), 'Body') | ||
}) | ||
t.deepEqual(headers, { | ||
hello: 'world', | ||
connection: 'upgrade', | ||
upgrade: 'websocket' | ||
}) | ||
socket.end() | ||
}) | ||
}) | ||
test('pool connect', (t) => { | ||
t.plan(1) | ||
const server = createServer((c) => { | ||
t.fail() | ||
}) | ||
server.on('connect', (req, socket, firstBodyChunk) => { | ||
socket.write('HTTP/1.1 200 Connection established\r\n\r\n') | ||
let data = firstBodyChunk.toString() | ||
socket.on('data', (buf) => { | ||
data += buf.toString() | ||
}) | ||
socket.on('end', () => { | ||
socket.end(data) | ||
}) | ||
}) | ||
t.tearDown(server.close.bind(server)) | ||
server.listen(0, async () => { | ||
const client = new Pool(`http://localhost:${server.address().port}`) | ||
t.tearDown(client.close.bind(client)) | ||
const { socket } = await client.connect({ | ||
path: '/' | ||
}) | ||
let recvData = '' | ||
socket.on('data', (d) => { | ||
recvData += d | ||
}) | ||
socket.on('end', () => { | ||
t.strictEqual(recvData.toString(), 'Body') | ||
}) | ||
socket.write('Body') | ||
socket.end() | ||
}) | ||
}) | ||
test('pool dispatch', (t) => { | ||
t.plan(2) | ||
const server = createServer((req, res) => { | ||
res.end('asd') | ||
}) | ||
t.tearDown(server.close.bind(server)) | ||
server.listen(0, async () => { | ||
const client = new Pool(`http://localhost:${server.address().port}`) | ||
t.tearDown(client.close.bind(client)) | ||
let buf = '' | ||
client.dispatch({ | ||
path: '/', | ||
method: 'GET' | ||
}, { | ||
onHeaders (statusCode, headers) { | ||
t.strictEqual(statusCode, 200) | ||
}, | ||
onData (chunk) { | ||
buf += chunk | ||
}, | ||
onComplete () { | ||
t.strictEqual(buf, 'asd') | ||
} | ||
}) | ||
}) | ||
}) |
290035
53
9447
43