undici
Advanced tools
Comparing version 1.0.1 to 1.0.2
@@ -36,3 +36,2 @@ 'use strict' | ||
kMaxAbortedPayload, | ||
kHostHeader, | ||
kParser, | ||
@@ -45,3 +44,2 @@ kSocket, | ||
const CRLF = Buffer.from('\r\n', 'ascii') | ||
const KEEP_ALIVE = Buffer.from('Connection: keep-alive\r\n', 'ascii') | ||
const TE_CHUNKED = Buffer.from('transfer-encoding: chunked\r\n', 'ascii') | ||
@@ -101,3 +99,2 @@ const TE_CHUNKED_EOF = Buffer.from('\r\n0\r\n\r\n', 'ascii') | ||
this[kUrl] = url | ||
this[kHostHeader] = Buffer.from(`Host: ${url.hostname}\r\n`, 'ascii') | ||
this[kSocketTimeout] = socketTimeout == null ? 30e3 : socketTimeout | ||
@@ -192,3 +189,3 @@ this[kRequestTimeout] = requestTimeout == null ? 30e3 : requestTimeout | ||
try { | ||
request = new Request(opts, callback) | ||
request = new Request(opts, this[kUrl].hostname, callback) | ||
} catch (err) { | ||
@@ -201,6 +198,2 @@ process.nextTick(callback, err, null) | ||
if (!this[kSocket] && !this[kRetryTimeout]) { | ||
connect(this) | ||
} | ||
resume(this) | ||
@@ -568,2 +561,7 @@ | ||
if (!client[kSocket] && !client[kRetryTimeout]) { | ||
connect(client) | ||
return | ||
} | ||
if (!client.connected) { | ||
@@ -601,5 +599,4 @@ return | ||
// Release memory for no longer required properties. | ||
request.path = null | ||
request.headers = null | ||
request.body = null | ||
request.headers = null | ||
} | ||
@@ -609,9 +606,6 @@ } | ||
function write (client, { | ||
host, | ||
method, | ||
path, | ||
header, | ||
body, | ||
streaming, | ||
chunked, | ||
headers, | ||
signal | ||
@@ -622,13 +616,4 @@ }) { | ||
socket.cork() | ||
socket.write(`${method} ${path} HTTP/1.1\r\n`, 'ascii') | ||
socket.write(KEEP_ALIVE) | ||
socket.write(header) | ||
if (!host) { | ||
socket.write(client[kHostHeader]) | ||
} | ||
if (headers) { | ||
socket.write(headers) | ||
} | ||
if (!body) { | ||
@@ -635,0 +620,0 @@ socket.write(CRLF) |
@@ -131,3 +131,3 @@ const { | ||
read () { | ||
if (body) { | ||
if (body && body.resume) { | ||
body.resume() | ||
@@ -225,5 +225,7 @@ } | ||
// TODO: body.destroy? | ||
body | ||
.on('data', function (chunk) { | ||
if (!ret.push(chunk)) { | ||
if (!ret.push(chunk) && this.pause) { | ||
this.pause() | ||
@@ -230,0 +232,0 @@ } |
@@ -69,5 +69,6 @@ 'use strict' | ||
requestTimeout | ||
}, callback) { | ||
}, hostname, callback) { | ||
super('UNDICI_REQ') | ||
assert(typeof hostname === 'string') | ||
assert(typeof callback === 'function') | ||
@@ -101,4 +102,2 @@ | ||
this.path = path | ||
this.streaming = body && typeof body.pipe === 'function' | ||
@@ -110,4 +109,2 @@ | ||
this.host = headers && Boolean(headers.host || headers.Host) | ||
this.chunked = !headers || headers['content-length'] === undefined | ||
@@ -133,3 +130,3 @@ | ||
let headersStr = '' | ||
let header = `${method} ${path} HTTP/1.1\r\n` | ||
@@ -140,11 +137,18 @@ if (headers) { | ||
const name = headerNames[i] | ||
headersStr += name + ': ' + headers[name] + '\r\n' | ||
header += name + ': ' + headers[name] + '\r\n' | ||
} | ||
} | ||
const hostHeader = headers && (headers.host || headers.Host) | ||
if (!hostHeader) { | ||
header += `host: ${hostname}\r\n` | ||
} | ||
header += 'connection: keep-alive\r\n' | ||
if (this.body && this.chunked && !this.streaming) { | ||
headersStr += `content-length: ${Buffer.byteLength(this.body)}\r\n` | ||
header += `content-length: ${Buffer.byteLength(this.body)}\r\n` | ||
} | ||
this.headers = headersStr ? Buffer.from(headersStr, 'ascii') : null | ||
this.header = Buffer.from(header, 'ascii') | ||
} | ||
@@ -200,5 +204,13 @@ | ||
if ( | ||
this.streaming && | ||
this.body && | ||
!this.body.destroyed && | ||
typeof this.body.destroy === 'function' | ||
) { | ||
this.body.destroy(err) | ||
} | ||
clearTimeout(this.timeout) | ||
this.timeout = null | ||
this.path = null | ||
this.body = null | ||
@@ -205,0 +217,0 @@ this.callback = null |
@@ -14,3 +14,2 @@ module.exports = { | ||
kError: Symbol('error'), | ||
kHostHeader: Symbol('host header buffer'), | ||
kOnDestroyed: Symbol('destroy callbacks'), | ||
@@ -17,0 +16,0 @@ kPipelining: Symbol('pipelinig'), |
{ | ||
"name": "undici", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"description": "An HTTP/1.1 client, written from scratch for Node.js", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -42,5 +42,4 @@ # undici | ||
The `url` will be used to extract the protocol and the domain/IP | ||
address. The path is discarded. | ||
`url` can be a string or a [`URL`](https://nodejs.org/api/url.html#url_class_url) object. | ||
It should only include the protocol, hostname, and the port. | ||
Options: | ||
@@ -186,3 +185,2 @@ | ||
const client = new Client'http://localhost:3000') | ||
@@ -295,4 +293,4 @@ const ee = new EventEmitter() | ||
`handler` should return a [`Writable`](https://nodejs.org/api/stream.html#stream_class_stream_writable) to which the response will be | ||
written to. Usually it should just return the `body` argument unless | ||
`handler` should return a [`Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable) from which the result will be | ||
read. Usually it should just return the `body` argument unless | ||
some kind of transformation needs to be performed based on e.g. | ||
@@ -331,3 +329,3 @@ `headers` or `statusCode`. | ||
}), | ||
fs.createReadStream('response.raw'), | ||
fs.createWriteStream('response.raw'), | ||
(err) => { | ||
@@ -334,0 +332,0 @@ if (err) { |
@@ -8,5 +8,6 @@ 'use strict' | ||
const { createReadStream } = require('fs') | ||
const { Readable } = require('stream') | ||
test('Abort before sending request (no body)', (t) => { | ||
t.plan(3) | ||
t.plan(4) | ||
@@ -40,5 +41,14 @@ let count = 0 | ||
client.request({ path: '/', method: 'GET', signal: ee }, (err, response) => { | ||
const body = new Readable({ read () { } }) | ||
body.on('error', (err) => { | ||
t.ok(err instanceof errors.RequestAbortedError) | ||
}) | ||
client.request({ | ||
path: '/', | ||
method: 'GET', | ||
signal: ee, | ||
body | ||
}, (err, response) => { | ||
t.ok(err instanceof errors.RequestAbortedError) | ||
}) | ||
@@ -45,0 +55,0 @@ ee.emit('abort') |
@@ -665,1 +665,30 @@ 'use strict' | ||
}) | ||
test('pipeline legacy stream', (t) => { | ||
t.plan(1) | ||
const server = createServer((req, res) => { | ||
res.write(Buffer.alloc(16e3)) | ||
setImmediate(() => { | ||
res.end(Buffer.alloc(16e3)) | ||
}) | ||
}) | ||
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 | ||
.pipeline({ path: '/', method: 'GET' }, ({ body }) => { | ||
const pt = new PassThrough() | ||
pt.pause = null | ||
return body.pipe(pt) | ||
}) | ||
.resume() | ||
.on('end', () => { | ||
t.pass() | ||
}) | ||
.end() | ||
}) | ||
}) |
194374
6172
522