Comparing version 4.8.1 to 4.8.2
# Connecting through a proxy | ||
Connecting through a proxy is possible by properly configuring the `Client` or `Pool` constructor and request. | ||
Connecting through a proxy is possible by: | ||
- Using [AgentProxy](docs/api/ProxyAgent.md). | ||
- Configuring `Client` or `Pool` constructor. | ||
The proxy url should be passed to the `Client` or `Pool` constructor, while the upstream server url | ||
@@ -6,0 +9,0 @@ should be added to every request call in the `path`. |
@@ -13,2 +13,3 @@ import Dispatcher = require('./types/dispatcher') | ||
import mockErrors = require('./types/mock-errors') | ||
import ProxyAgent from './types/proxy-agent' | ||
import { request, pipeline, stream, connect, upgrade } from './types/api' | ||
@@ -20,3 +21,3 @@ | ||
export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, MockClient, MockPool, MockAgent, mockErrors } | ||
export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, MockClient, MockPool, MockAgent, mockErrors, ProxyAgent } | ||
export default Undici | ||
@@ -23,0 +24,0 @@ |
@@ -17,2 +17,3 @@ 'use strict' | ||
const mockErrors = require('./lib/mock/mock-errors') | ||
const ProxyAgent = require('./lib/proxy-agent') | ||
@@ -30,2 +31,3 @@ const nodeVersion = process.versions.node.split('.') | ||
module.exports.Agent = Agent | ||
module.exports.ProxyAgent = ProxyAgent | ||
@@ -32,0 +34,0 @@ module.exports.buildConnector = buildConnector |
@@ -400,72 +400,73 @@ 'use strict' | ||
const { resolve } = require('path') | ||
const { readFileSync } = require('fs') | ||
const constants = require('./llhttp/constants') | ||
const EMPTY_BUF = Buffer.alloc(0) | ||
let llhttpPromise | ||
let llhttpInstance | ||
function lazyllhttp () { | ||
if (!llhttpInstance) { | ||
let mod | ||
try { | ||
mod = new WebAssembly.Module(readFileSync(resolve(__dirname, './llhttp/llhttp_simd.wasm'))) | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
async function lazyllhttp () { | ||
const { resolve } = require('path') | ||
const { readFile } = require('fs').promises | ||
// 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. | ||
mod = new WebAssembly.Module(readFileSync(resolve(__dirname, './llhttp/llhttp.wasm'))) | ||
} | ||
let mod | ||
try { | ||
mod = await WebAssembly.compile(await readFile(resolve(__dirname, './llhttp/llhttp_simd.wasm'))) | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
llhttpInstance = new WebAssembly.Instance(mod, { | ||
env: { | ||
/* eslint-disable camelcase */ | ||
// 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. | ||
mod = await WebAssembly.compile(await readFile(resolve(__dirname, './llhttp/llhttp.wasm'))) | ||
} | ||
wasm_on_url: (p, at, len) => { | ||
/* istanbul ignore next */ | ||
return 0 | ||
}, | ||
wasm_on_status: (p, at, len) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
const start = at - currentBufferPtr | ||
const end = start + len | ||
return currentParser.onStatus(currentBufferRef.slice(start, end)) || 0 | ||
}, | ||
wasm_on_message_begin: (p) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
return currentParser.onMessageBegin() || 0 | ||
}, | ||
wasm_on_header_field: (p, at, len) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
const start = at - currentBufferPtr | ||
const end = start + len | ||
return currentParser.onHeaderField(currentBufferRef.slice(start, end)) || 0 | ||
}, | ||
wasm_on_header_value: (p, at, len) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
const start = at - currentBufferPtr | ||
const end = start + len | ||
return currentParser.onHeaderValue(currentBufferRef.slice(start, end)) || 0 | ||
}, | ||
wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0 | ||
}, | ||
wasm_on_body: (p, at, len) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
const start = at - currentBufferPtr | ||
const end = start + len | ||
return currentParser.onBody(currentBufferRef.slice(start, end)) || 0 | ||
}, | ||
wasm_on_message_complete: (p) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
return currentParser.onMessageComplete() || 0 | ||
} | ||
llhttpInstance = new WebAssembly.Instance(mod, { | ||
env: { | ||
/* eslint-disable camelcase */ | ||
/* eslint-enable camelcase */ | ||
wasm_on_url: (p, at, len) => { | ||
/* istanbul ignore next */ | ||
return 0 | ||
}, | ||
wasm_on_status: (p, at, len) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
const start = at - currentBufferPtr | ||
const end = start + len | ||
return currentParser.onStatus(currentBufferRef.slice(start, end)) || 0 | ||
}, | ||
wasm_on_message_begin: (p) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
return currentParser.onMessageBegin() || 0 | ||
}, | ||
wasm_on_header_field: (p, at, len) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
const start = at - currentBufferPtr | ||
const end = start + len | ||
return currentParser.onHeaderField(currentBufferRef.slice(start, end)) || 0 | ||
}, | ||
wasm_on_header_value: (p, at, len) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
const start = at - currentBufferPtr | ||
const end = start + len | ||
return currentParser.onHeaderValue(currentBufferRef.slice(start, end)) || 0 | ||
}, | ||
wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0 | ||
}, | ||
wasm_on_body: (p, at, len) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
const start = at - currentBufferPtr | ||
const end = start + len | ||
return currentParser.onBody(currentBufferRef.slice(start, end)) || 0 | ||
}, | ||
wasm_on_message_complete: (p) => { | ||
assert.strictEqual(currentParser.ptr, p) | ||
return currentParser.onMessageComplete() || 0 | ||
} | ||
}) | ||
} | ||
/* eslint-enable camelcase */ | ||
} | ||
}) | ||
return llhttpInstance | ||
@@ -484,6 +485,6 @@ } | ||
class Parser { | ||
constructor (client, socket) { | ||
constructor (client, socket, { exports }) { | ||
assert(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0) | ||
this.llhttp = lazyllhttp().exports | ||
this.llhttp = exports | ||
this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE) | ||
@@ -1101,3 +1102,3 @@ this.client = client | ||
function connect (client) { | ||
async function connect (client) { | ||
assert(!client[kConnecting]) | ||
@@ -1134,74 +1135,93 @@ assert(!client[kSocket]) | ||
client[kConnector]({ | ||
host, | ||
hostname, | ||
protocol, | ||
port, | ||
servername: client[kServerName] | ||
}, function (err, socket) { | ||
client[kConnecting] = false | ||
if (err) { | ||
if (channels.connectError.hasSubscribers) { | ||
channels.connectError.publish({ | ||
connectParams: { | ||
host, | ||
hostname, | ||
protocol, | ||
port, | ||
servername: client[kServerName] | ||
}, | ||
connector: client[kConnector], | ||
error: err | ||
}) | ||
try { | ||
if (!llhttpInstance) { | ||
if (!llhttpPromise) { | ||
llhttpPromise = lazyllhttp() | ||
} | ||
await llhttpPromise | ||
assert(llhttpInstance) | ||
llhttpPromise = null | ||
} | ||
if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') { | ||
assert(client[kRunning] === 0) | ||
while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { | ||
const request = client[kQueue][client[kPendingIdx]++] | ||
errorRequest(client, request, err) | ||
const socket = await new Promise((resolve, reject) => { | ||
client[kConnector]({ | ||
host, | ||
hostname, | ||
protocol, | ||
port, | ||
servername: client[kServerName] | ||
}, (err, socket) => { | ||
if (err) { | ||
reject(err) | ||
} else { | ||
resolve(socket) | ||
} | ||
} else { | ||
onError(client, err) | ||
} | ||
}) | ||
}) | ||
client.emit('connectionError', client[kUrl], [client], err) | ||
} else { | ||
assert(socket) | ||
client[kConnecting] = false | ||
client[kSocket] = socket | ||
assert(socket) | ||
socket[kNoRef] = false | ||
socket[kWriting] = false | ||
socket[kReset] = false | ||
socket[kBlocking] = false | ||
socket[kError] = null | ||
socket[kParser] = new Parser(client, socket) | ||
socket[kClient] = client | ||
socket | ||
.on('error', onSocketError) | ||
.on('readable', onSocketReadable) | ||
.on('end', onSocketEnd) | ||
.on('close', onSocketClose) | ||
client[kSocket] = socket | ||
if (channels.connected.hasSubscribers) { | ||
channels.connected.publish({ | ||
connectParams: { | ||
host, | ||
hostname, | ||
protocol, | ||
port, | ||
servername: client[kServerName] | ||
}, | ||
connector: client[kConnector], | ||
socket | ||
}) | ||
} | ||
socket[kNoRef] = false | ||
socket[kWriting] = false | ||
socket[kReset] = false | ||
socket[kBlocking] = false | ||
socket[kError] = null | ||
socket[kParser] = new Parser(client, socket, llhttpInstance) | ||
socket[kClient] = client | ||
socket | ||
.on('error', onSocketError) | ||
.on('readable', onSocketReadable) | ||
.on('end', onSocketEnd) | ||
.on('close', onSocketClose) | ||
client.emit('connect', client[kUrl], [client]) | ||
if (channels.connected.hasSubscribers) { | ||
channels.connected.publish({ | ||
connectParams: { | ||
host, | ||
hostname, | ||
protocol, | ||
port, | ||
servername: client[kServerName] | ||
}, | ||
connector: client[kConnector], | ||
socket | ||
}) | ||
} | ||
resume(client) | ||
}) | ||
client.emit('connect', client[kUrl], [client]) | ||
} catch (err) { | ||
client[kConnecting] = false | ||
if (channels.connectError.hasSubscribers) { | ||
channels.connectError.publish({ | ||
connectParams: { | ||
host, | ||
hostname, | ||
protocol, | ||
port, | ||
servername: client[kServerName] | ||
}, | ||
connector: client[kConnector], | ||
error: err | ||
}) | ||
} | ||
if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') { | ||
assert(client[kRunning] === 0) | ||
while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { | ||
const request = client[kQueue][client[kPendingIdx]++] | ||
errorRequest(client, request, err) | ||
} | ||
} else { | ||
onError(client, err) | ||
} | ||
client.emit('connectionError', client[kUrl], [client], err) | ||
} | ||
resume(client) | ||
} | ||
@@ -1208,0 +1228,0 @@ |
@@ -43,3 +43,4 @@ module.exports = { | ||
kStrictContentLength: Symbol('strict content length'), | ||
kMaxRedirections: Symbol('maxRedirections') | ||
kMaxRedirections: Symbol('maxRedirections'), | ||
kProxy: Symbol('proxy agent options') | ||
} |
{ | ||
"name": "undici", | ||
"version": "4.8.1", | ||
"version": "4.8.2", | ||
"description": "An HTTP/1.1 client, written from scratch for Node.js", | ||
@@ -5,0 +5,0 @@ "homepage": "https://undici.nodejs.org", |
631576
90
9924