Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Pool/Client.url #527

Merged
merged 2 commits into from
Jan 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,10 @@ there might still be some progress on dispatched requests.

Returns a promise if no callback is provided.

#### `client.url: URL`

Returns url passed to `undici.Pool(url, opts)`.

#### `client.pipelining: Number`

Property to get and set the pipelining factor.
Expand Down Expand Up @@ -570,6 +574,10 @@ Options:
`Pool` does not guarantee that requests are dispatched in
order of invocation.

#### `pool.url: URL`

Returns url passed to `undici.Pool(url, opts)`.

#### `pool.connected: Integer`

Number of active connections in pool.
Expand Down
35 changes: 7 additions & 28 deletions lib/core/client.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use strict'

const { URL } = require('url')
const net = require('net')
const tls = require('tls')
const HTTPParser = require('../node/http-parser')
Expand Down Expand Up @@ -108,38 +107,14 @@ class Client extends EventEmitter {
throw new InvalidArgumentError('unsupported maxKeepAliveTimeout, use keepAliveMaxTimeout instead')
}

if (typeof url === 'string') {
url = new URL(url)
}

if (!url || typeof url !== 'object') {
throw new InvalidArgumentError('invalid url')
}

if (url.port != null && url.port !== '' && !Number.isFinite(parseInt(url.port))) {
throw new InvalidArgumentError('invalid port')
if (maxHeaderSize != null && !Number.isFinite(maxHeaderSize)) {
throw new InvalidArgumentError('invalid maxHeaderSize')
}

if (socketPath != null && typeof socketPath !== 'string') {
throw new InvalidArgumentError('invalid socketPath')
}

if (url.hostname != null && typeof url.hostname !== 'string') {
throw new InvalidArgumentError('invalid hostname')
}

if (!/https?/.test(url.protocol)) {
throw new InvalidArgumentError('invalid protocol')
}

if (/\/.+/.test(url.pathname) || url.search || url.hash) {
throw new InvalidArgumentError('invalid url')
}

if (maxHeaderSize != null && !Number.isFinite(maxHeaderSize)) {
throw new InvalidArgumentError('invalid maxHeaderSize')
}

if (keepAliveTimeout != null && (!Number.isFinite(keepAliveTimeout) || keepAliveTimeout <= 0)) {
throw new InvalidArgumentError('invalid keepAliveTimeout')
}
Expand All @@ -163,7 +138,7 @@ class Client extends EventEmitter {
this[kSocket] = null
this[kPipelining] = pipelining != null ? pipelining : 1
this[kMaxHeadersSize] = maxHeaderSize || 16384
this[kUrl] = url
this[kUrl] = util.parseOrigin(url)
this[kSocketPath] = socketPath
this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout
this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 600e3 : keepAliveMaxTimeout
Expand Down Expand Up @@ -196,6 +171,10 @@ class Client extends EventEmitter {
this[kPendingIdx] = 0
}

get url () {
return this[kUrl]
}

get pipelining () {
return this[kPipelining]
}
Expand Down
40 changes: 39 additions & 1 deletion lib/core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,51 @@ const { kDestroyed } = require('./symbols')
const { IncomingMessage } = require('http')
const util = require('util')
const net = require('net')
const { NotSupportedError } = require('./errors')
const { NotSupportedError, InvalidArgumentError } = require('./errors')

function nop () {}

function isStream (body) {
return !!(body && typeof body.on === 'function')
}

function parseOrigin (url) {
if (typeof url === 'string') {
url = new URL(url)
}

if (!url || typeof url !== 'object') {
throw new InvalidArgumentError('invalid url')
}

if (url.port != null && url.port !== '' && !Number.isFinite(parseInt(url.port))) {
throw new InvalidArgumentError('invalid port')
}

if (url.hostname != null && typeof url.hostname !== 'string') {
throw new InvalidArgumentError('invalid hostname')
}

if (!/https?/.test(url.protocol)) {
throw new InvalidArgumentError('invalid protocol')
}

if (/\/.+/.test(url.pathname) || url.search || url.hash) {
throw new InvalidArgumentError('invalid url')
}

if (!(url instanceof URL)) {
const port = url.port || {
'http:': 80,
'https:': 443
}[url.protocol]
assert(port != null)
url = new URL(`${url.protocol}//${url.hostname}:${port}`)
}

return url
}

function getServerName (host) {
if (!host) {
return null
Expand Down Expand Up @@ -152,6 +189,7 @@ function weakCache (fn) {

module.exports = {
nop,
parseOrigin,
getServerName,
errnoException,
isStream,
Expand Down
9 changes: 7 additions & 2 deletions lib/pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const {
ClientDestroyedError
} = require('./core/errors')
const FixedQueue = require('./node/fixed-queue')
const util = require('./core/util')

const kClients = Symbol('clients')
const kNeedDrain = Symbol('needDrain')
Expand All @@ -25,7 +26,7 @@ const kConnected = Symbol('connected')
const kConnections = Symbol('connections')

class Pool extends EventEmitter {
constructor (url, opts = {}) {
constructor (origin, opts = {}) {
super()

const { connections, ...options } = opts
Expand All @@ -35,7 +36,7 @@ class Pool extends EventEmitter {
}

this[kConnections] = connections || null
this[kUrl] = url
this[kUrl] = util.parseOrigin(origin)
this[kOptions] = JSON.parse(JSON.stringify(options))
this[kQueue] = new FixedQueue()
this[kClosedPromise] = null
Expand Down Expand Up @@ -83,6 +84,10 @@ class Pool extends EventEmitter {
}
}

get url () {
return this[kUrl]
}

get connected () {
return this[kConnected]
}
Expand Down
10 changes: 6 additions & 4 deletions test/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const { kSocket } = require('../lib/core/symbols')
const EE = require('events')

test('basic get', (t) => {
t.plan(23)
t.plan(24)

const server = createServer((req, res) => {
t.strictEqual('/', req.url)
Expand All @@ -34,6 +34,8 @@ test('basic get', (t) => {
})
t.tearDown(client.close.bind(client))

t.strictEqual(client.url.origin, `http://localhost:${server.address().port}`)

const signal = new EE()
client.request({
signal,
Expand Down Expand Up @@ -616,7 +618,7 @@ test('url-like url', (t) => {
const client = new Client({
hostname: 'localhost',
port: server.address().port,
protocol: 'http'
protocol: 'http:'
})
t.tearDown(client.close.bind(client))

Expand All @@ -642,7 +644,7 @@ test('an absolute url as path', (t) => {
const client = new Client({
hostname: 'localhost',
port: server.address().port,
protocol: 'http'
protocol: 'http:'
})
t.tearDown(client.close.bind(client))

Expand All @@ -665,7 +667,7 @@ test('multiple destroy callback', (t) => {
const client = new Client({
hostname: 'localhost',
port: server.address().port,
protocol: 'http'
protocol: 'http:'
})
t.tearDown(client.destroy.bind(client))

Expand Down
4 changes: 3 additions & 1 deletion test/pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ test('connect/disconnect event(s)', (t) => {
})

test('basic get', (t) => {
t.plan(13)
t.plan(14)

const server = createServer((req, res) => {
t.strictEqual('/', req.url)
Expand All @@ -70,6 +70,8 @@ test('basic get', (t) => {
const client = undici(`http://localhost:${server.address().port}`)
t.tearDown(client.destroy.bind(client))

t.strictEqual(client.url.origin, `http://localhost:${server.address().port}`)

client.request({ path: '/', method: 'GET' }, (err, { statusCode, headers, body }) => {
t.error(err)
t.strictEqual(statusCode, 200)
Expand Down