package-rebuilds/pkgs/node-undici/node-undici-5.28.4+dfsg1+~cs23.12.11/test/client-dispatch.js
Fabian Grünbichler afee63929c add node-undici for libgit2 1.8.1
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
2024-09-10 11:23:24 +02:00

785 lines
17 KiB
JavaScript

'use strict'
const { test } = require('tap')
const http = require('http')
const { Client, Pool, errors } = require('..')
const stream = require('stream')
test('dispatch invalid opts', (t) => {
t.plan(14)
const client = new Client('http://localhost:5000')
try {
client.dispatch({
path: '/',
method: 'GET',
upgrade: 1
}, null)
} catch (err) {
t.type(err, errors.InvalidArgumentError)
t.equal(err.message, 'handler must be an object')
}
try {
client.dispatch({
path: '/',
method: 'GET',
upgrade: 1
}, 'asd')
} catch (err) {
t.type(err, errors.InvalidArgumentError)
t.equal(err.message, 'handler must be an object')
}
client.dispatch({
path: '/',
method: 'GET',
upgrade: 1
}, {
onError (err) {
t.type(err, errors.InvalidArgumentError)
t.equal(err.message, 'upgrade must be a string')
}
})
client.dispatch({
path: '/',
method: 'GET',
headersTimeout: 'asd'
}, {
onError (err) {
t.type(err, errors.InvalidArgumentError)
t.equal(err.message, 'invalid headersTimeout')
}
})
client.dispatch({
path: '/',
method: 'GET',
bodyTimeout: 'asd'
}, {
onError (err) {
t.type(err, errors.InvalidArgumentError)
t.equal(err.message, 'invalid bodyTimeout')
}
})
client.dispatch({
origin: 'another',
path: '/',
method: 'GET',
bodyTimeout: 'asd'
}, {
onError (err) {
t.type(err, errors.InvalidArgumentError)
t.equal(err.message, 'invalid bodyTimeout')
}
})
client.dispatch(null, {
onError (err) {
t.type(err, errors.InvalidArgumentError)
t.equal(err.message, 'opts must be an object.')
}
})
})
test('basic dispatch get', (t) => {
t.plan(11)
const server = http.createServer((req, res) => {
t.equal('/', req.url)
t.equal('GET', req.method)
t.equal(`localhost:${server.address().port}`, req.headers.host)
t.equal(undefined, req.headers.foo)
t.equal('bar', req.headers.bar)
t.equal('', req.headers.baz)
t.equal(undefined, req.headers['content-length'])
res.end('hello')
})
t.teardown(server.close.bind(server))
const reqHeaders = {
foo: undefined,
bar: 'bar',
baz: null
}
server.listen(0, () => {
const client = new Client(`http://localhost:${server.address().port}`)
t.teardown(client.close.bind(client))
const bufs = []
client.dispatch({
path: '/',
method: 'GET',
headers: reqHeaders
}, {
onConnect () {
},
onHeaders (statusCode, headers) {
t.equal(statusCode, 200)
t.equal(Array.isArray(headers), true)
},
onData (buf) {
bufs.push(buf)
},
onComplete (trailers) {
t.same(trailers, [])
t.equal('hello', Buffer.concat(bufs).toString('utf8'))
},
onError () {
t.fail()
}
})
})
})
test('trailers dispatch get', (t) => {
t.plan(12)
const server = http.createServer((req, res) => {
t.equal('/', req.url)
t.equal('GET', req.method)
t.equal(`localhost:${server.address().port}`, req.headers.host)
t.equal(undefined, req.headers.foo)
t.equal('bar', req.headers.bar)
t.equal(undefined, req.headers['content-length'])
res.addTrailers({ 'Content-MD5': 'test' })
res.setHeader('Content-Type', 'text/plain')
res.setHeader('Trailer', 'Content-MD5')
res.end('hello')
})
t.teardown(server.close.bind(server))
const reqHeaders = {
foo: undefined,
bar: 'bar'
}
server.listen(0, () => {
const client = new Client(`http://localhost:${server.address().port}`)
t.teardown(client.close.bind(client))
const bufs = []
client.dispatch({
path: '/',
method: 'GET',
headers: reqHeaders
}, {
onConnect () {
},
onHeaders (statusCode, headers) {
t.equal(statusCode, 200)
t.equal(Array.isArray(headers), true)
{
const contentTypeIdx = headers.findIndex(x => x.toString() === 'Content-Type')
t.equal(headers[contentTypeIdx + 1].toString(), 'text/plain')
}
},
onData (buf) {
bufs.push(buf)
},
onComplete (trailers) {
t.equal(Array.isArray(trailers), true)
{
const contentMD5Idx = trailers.findIndex(x => x.toString() === 'Content-MD5')
t.equal(trailers[contentMD5Idx + 1].toString(), 'test')
}
t.equal('hello', Buffer.concat(bufs).toString('utf8'))
},
onError () {
t.fail()
}
})
})
})
test('dispatch onHeaders error', (t) => {
t.plan(1)
const server = http.createServer((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.close.bind(client))
const _err = new Error()
client.dispatch({
path: '/',
method: 'GET'
}, {
onConnect () {
},
onHeaders (statusCode, headers) {
throw _err
},
onData (buf) {
t.fail()
},
onComplete (trailers) {
t.fail()
},
onError (err) {
t.equal(err, _err)
}
})
})
})
test('dispatch onComplete error', (t) => {
t.plan(2)
const server = http.createServer((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.close.bind(client))
const _err = new Error()
client.dispatch({
path: '/',
method: 'GET'
}, {
onConnect () {
},
onHeaders (statusCode, headers) {
t.pass()
},
onData (buf) {
t.fail()
},
onComplete (trailers) {
throw _err
},
onError (err) {
t.equal(err, _err)
}
})
})
})
test('dispatch onData error', (t) => {
t.plan(2)
const server = http.createServer((req, res) => {
res.end('ad')
})
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 _err = new Error()
client.dispatch({
path: '/',
method: 'GET'
}, {
onConnect () {
},
onHeaders (statusCode, headers) {
t.pass()
},
onData (buf) {
throw _err
},
onComplete (trailers) {
t.fail()
},
onError (err) {
t.equal(err, _err)
}
})
})
})
test('dispatch onConnect error', (t) => {
t.plan(1)
const server = http.createServer((req, res) => {
res.end('ad')
})
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 _err = new Error()
client.dispatch({
path: '/',
method: 'GET'
}, {
onConnect () {
throw _err
},
onHeaders (statusCode, headers) {
t.fail()
},
onData (buf) {
t.fail()
},
onComplete (trailers) {
t.fail()
},
onError (err) {
t.equal(err, _err)
}
})
})
})
test('connect call onUpgrade once', (t) => {
t.plan(2)
const server = http.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 Client(`http://localhost:${server.address().port}`)
t.teardown(client.close.bind(client))
let recvData = ''
let count = 0
client.dispatch({
method: 'CONNECT',
path: '/'
}, {
onConnect () {
},
onHeaders (statusCode, headers) {
t.pass('should not throw')
},
onUpgrade (statusCode, headers, socket) {
t.equal(count++, 0)
socket.on('data', (d) => {
recvData += d
})
socket.on('end', () => {
t.equal(recvData.toString(), 'Body')
})
socket.write('Body')
socket.end()
},
onData (buf) {
t.fail()
},
onComplete (trailers) {
t.fail()
},
onError () {
t.fail()
}
})
})
})
test('dispatch onConnect missing', (t) => {
t.plan(1)
const server = http.createServer((req, res) => {
res.end('ad')
})
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.dispatch({
path: '/',
method: 'GET'
}, {
onHeaders (statusCode, headers) {
t.pass('should not throw')
},
onData (buf) {
t.pass('should not throw')
},
onComplete (trailers) {
t.pass('should not throw')
},
onError (err) {
t.equal(err.code, 'UND_ERR_INVALID_ARG')
}
})
})
})
test('dispatch onHeaders missing', (t) => {
t.plan(1)
const server = http.createServer((req, res) => {
res.end('ad')
})
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.dispatch({
path: '/',
method: 'GET'
}, {
onConnect () {
},
onData (buf) {
t.fail('should not throw')
},
onComplete (trailers) {
t.fail('should not throw')
},
onError (err) {
t.equal(err.code, 'UND_ERR_INVALID_ARG')
}
})
})
})
test('dispatch onData missing', (t) => {
t.plan(1)
const server = http.createServer((req, res) => {
res.end('ad')
})
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.dispatch({
path: '/',
method: 'GET'
}, {
onConnect () {
},
onHeaders (statusCode, headers) {
t.fail('should not throw')
},
onComplete (trailers) {
t.fail('should not throw')
},
onError (err) {
t.equal(err.code, 'UND_ERR_INVALID_ARG')
}
})
})
})
test('dispatch onComplete missing', (t) => {
t.plan(1)
const server = http.createServer((req, res) => {
res.end('ad')
})
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.dispatch({
path: '/',
method: 'GET'
}, {
onConnect () {
},
onHeaders (statusCode, headers) {
t.fail()
},
onData (buf) {
t.fail()
},
onError (err) {
t.equal(err.code, 'UND_ERR_INVALID_ARG')
}
})
})
})
test('dispatch onError missing', (t) => {
t.plan(1)
const server = http.createServer((req, res) => {
res.end('ad')
})
t.teardown(server.close.bind(server))
server.listen(0, () => {
const client = new Client(`http://localhost:${server.address().port}`)
t.teardown(client.close.bind(client))
try {
client.dispatch({
path: '/',
method: 'GET'
}, {
onConnect () {
},
onHeaders (statusCode, headers) {
t.fail()
},
onData (buf) {
t.fail()
},
onComplete (trailers) {
t.fail()
}
})
} catch (err) {
t.equal(err.code, 'UND_ERR_INVALID_ARG')
}
})
})
test('dispatch CONNECT onUpgrade missing', (t) => {
t.plan(2)
const server = http.createServer((req, res) => {
res.end('ad')
})
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.dispatch({
path: '/',
method: 'GET',
upgrade: 'Websocket'
}, {
onConnect () {
},
onHeaders (statusCode, headers) {
},
onError (err) {
t.equal(err.code, 'UND_ERR_INVALID_ARG')
t.equal(err.message, 'invalid onUpgrade method')
}
})
})
})
test('dispatch upgrade onUpgrade missing', (t) => {
t.plan(2)
const server = http.createServer((req, res) => {
res.end('ad')
})
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.dispatch({
path: '/',
method: 'GET',
upgrade: 'Websocket'
}, {
onConnect () {
},
onHeaders (statusCode, headers) {
},
onError (err) {
t.equal(err.code, 'UND_ERR_INVALID_ARG')
t.equal(err.message, 'invalid onUpgrade method')
}
})
})
})
test('dispatch pool onError missing', (t) => {
t.plan(2)
const server = http.createServer((req, res) => {
res.end('ad')
})
t.teardown(server.close.bind(server))
server.listen(0, () => {
const client = new Pool(`http://localhost:${server.address().port}`)
t.teardown(client.close.bind(client))
try {
client.dispatch({
path: '/',
method: 'GET',
upgrade: 'Websocket'
}, {
})
} catch (err) {
t.equal(err.code, 'UND_ERR_INVALID_ARG')
t.equal(err.message, 'invalid onError method')
}
})
})
test('dispatch onBodySent not a function', (t) => {
t.plan(2)
const server = http.createServer((req, res) => {
res.end('ad')
})
t.teardown(server.close.bind(server))
server.listen(0, () => {
const client = new Pool(`http://localhost:${server.address().port}`)
t.teardown(client.close.bind(client))
client.dispatch({
path: '/',
method: 'GET'
}, {
onBodySent: '42',
onConnect () {},
onHeaders () {},
onData () {},
onError (err) {
t.equal(err.code, 'UND_ERR_INVALID_ARG')
t.equal(err.message, 'invalid onBodySent method')
}
})
})
})
test('dispatch onBodySent buffer', (t) => {
t.plan(3)
const server = http.createServer((req, res) => {
res.end('ad')
})
t.teardown(server.close.bind(server))
server.listen(0, () => {
const client = new Pool(`http://localhost:${server.address().port}`)
t.teardown(client.close.bind(client))
const body = 'hello 🚀'
client.dispatch({
path: '/',
method: 'POST',
body
}, {
onBodySent (chunk) {
t.equal(chunk.toString(), body)
},
onRequestSent () {
t.pass()
},
onError (err) {
throw err
},
onConnect () {},
onHeaders () {},
onData () {},
onComplete () {
t.pass()
}
})
})
})
test('dispatch onBodySent stream', (t) => {
t.plan(8)
const server = http.createServer((req, res) => {
res.end('ad')
})
t.teardown(server.close.bind(server))
const chunks = ['he', 'llo', 'world', '🚀']
const toSendBytes = chunks.reduce((a, b) => a + Buffer.byteLength(b), 0)
const body = stream.Readable.from(chunks)
server.listen(0, () => {
const client = new Pool(`http://localhost:${server.address().port}`)
t.teardown(client.close.bind(client))
let sentBytes = 0
let currentChunk = 0
client.dispatch({
path: '/',
method: 'POST',
body
}, {
onBodySent (chunk) {
t.equal(chunks[currentChunk++], chunk)
sentBytes += Buffer.byteLength(chunk)
},
onRequestSent () {
t.pass()
},
onError (err) {
throw err
},
onConnect () {},
onHeaders () {},
onData () {},
onComplete () {
t.equal(currentChunk, chunks.length)
t.equal(sentBytes, toSendBytes)
t.pass()
}
})
})
})
test('dispatch onBodySent async-iterable', (t) => {
const server = http.createServer((req, res) => {
res.end('ad')
})
t.teardown(server.close.bind(server))
const chunks = ['he', 'llo', 'world', '🚀']
const toSendBytes = chunks.reduce((a, b) => a + Buffer.byteLength(b), 0)
server.listen(0, () => {
const client = new Pool(`http://localhost:${server.address().port}`)
t.teardown(client.close.bind(client))
let sentBytes = 0
let currentChunk = 0
client.dispatch({
path: '/',
method: 'POST',
body: chunks
}, {
onBodySent (chunk) {
t.equal(chunks[currentChunk++], chunk)
sentBytes += Buffer.byteLength(chunk)
},
onError (err) {
throw err
},
onConnect () {},
onHeaders () {},
onData () {},
onComplete () {
t.equal(currentChunk, chunks.length)
t.equal(sentBytes, toSendBytes)
t.end()
}
})
})
})