Skip to content
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
226 changes: 226 additions & 0 deletions test/http2-abort.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
'use strict'

const { tspl } = require('@matteo.collina/tspl')
const { test, after } = require('node:test')
const { createSecureServer } = require('node:http2')
const { once } = require('node:events')

const pem = require('@metcoder95/https-pem')

const { Client } = require('..')

test('#2364 - Concurrent aborts', async t => {
t = tspl(t, { plan: 10 })

const server = createSecureServer(await pem.generate({ opts: { keySize: 2048 } }))

server.on('stream', (stream, headers, _flags, rawHeaders) => {
setTimeout(() => {
stream.respond({
'content-type': 'text/plain; charset=utf-8',
'x-custom-h2': 'hello',
':status': 200
})
stream.end('hello h2!')
}, 100)
})

after(() => server.close())
await once(server.listen(0), 'listening')

const client = new Client(`https://localhost:${server.address().port}`, {
connect: {
rejectUnauthorized: false
},
allowH2: true
})

after(() => client.close())
const signal = AbortSignal.timeout(100)

client.request(
{
path: '/1',
method: 'GET',
headers: {
'x-my-header': 'foo'
}
},
(err, response) => {
t.ifError(err)
t.strictEqual(
response.headers['content-type'],
'text/plain; charset=utf-8'
)
t.strictEqual(response.headers['x-custom-h2'], 'hello')
t.strictEqual(response.statusCode, 200)
}
)

client.request(
{
path: '/2',
method: 'GET',
headers: {
'x-my-header': 'foo'
},
signal
},
(err, response) => {
t.strictEqual(err.name, 'TimeoutError')
}
)

client.request(
{
path: '/3',
method: 'GET',
headers: {
'x-my-header': 'foo'
}
},
(err, response) => {
t.ifError(err)
t.strictEqual(
response.headers['content-type'],
'text/plain; charset=utf-8'
)
t.strictEqual(response.headers['x-custom-h2'], 'hello')
t.strictEqual(response.statusCode, 200)
}
)

client.request(
{
path: '/4',
method: 'GET',
headers: {
'x-my-header': 'foo'
},
signal
},
(err, response) => {
t.strictEqual(err.name, 'TimeoutError')
}
)

await t.completed
})

test('#2364 - Concurrent aborts (2nd variant)', async t => {
t = tspl(t, { plan: 10 })

const server = createSecureServer(await pem.generate({ opts: { keySize: 2048 } }))
let counter = 0

server.on('stream', (stream, headers, _flags, rawHeaders) => {
counter++

if (counter % 2 === 0) {
setTimeout(() => {
if (stream.destroyed) {
return
}

stream.respond({
'content-type': 'text/plain; charset=utf-8',
'x-custom-h2': 'hello',
':status': 200
})

stream.end('hello h2!')
}, 400)

return
}

stream.respond({
'content-type': 'text/plain; charset=utf-8',
'x-custom-h2': 'hello',
':status': 200
})

stream.end('hello h2!')
})

after(() => server.close())
await once(server.listen(0), 'listening')

const client = new Client(`https://localhost:${server.address().port}`, {
connect: {
rejectUnauthorized: false
},
allowH2: true
})
after(() => client.close())

const signal = AbortSignal.timeout(300)

client.request(
{
path: '/1',
method: 'GET',
headers: {
'x-my-header': 'foo'
}
},
(err, response) => {
t.ifError(err)
t.strictEqual(
response.headers['content-type'],
'text/plain; charset=utf-8'
)
t.strictEqual(response.headers['x-custom-h2'], 'hello')
t.strictEqual(response.statusCode, 200)
}
)

client.request(
{
path: '/2',
method: 'GET',
headers: {
'x-my-header': 'foo'
},
signal
},
(err, response) => {
t.strictEqual(err.name, 'TimeoutError')
}
)

client.request(
{
path: '/3',
method: 'GET',
headers: {
'x-my-header': 'foo'
}
},
(err, response) => {
t.ifError(err)
t.strictEqual(
response.headers['content-type'],
'text/plain; charset=utf-8'
)
t.strictEqual(response.headers['x-custom-h2'], 'hello')
t.strictEqual(response.statusCode, 200)
}
)

client.request(
{
path: '/4',
method: 'GET',
headers: {
'x-my-header': 'foo'
},
signal
},
(err, response) => {
t.strictEqual(err.name, 'TimeoutError')
}
)

await t.completed
})
61 changes: 61 additions & 0 deletions test/http2-agent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use strict'

const { tspl } = require('@matteo.collina/tspl')
const { test, after } = require('node:test')
const { createSecureServer } = require('node:http2')
const { once } = require('node:events')

const pem = require('@metcoder95/https-pem')

const { Agent } = require('..')

test('Agent should support H2 connection', async t => {
t = tspl(t, { plan: 6 })

const body = []
const server = createSecureServer(await pem.generate({ opts: { keySize: 2048 } }))

server.on('stream', (stream, headers) => {
t.strictEqual(headers['x-my-header'], 'foo')
t.strictEqual(headers[':method'], 'GET')
stream.respond({
'content-type': 'text/plain; charset=utf-8',
'x-custom-h2': 'hello',
':status': 200
})
stream.end('hello h2!')
})

after(() => server.close())
await once(server.listen(0), 'listening')

const client = new Agent({
connect: {
rejectUnauthorized: false
},
allowH2: true
})
after(() => client.close())

const response = await client.request({
origin: `https://localhost:${server.address().port}`,
path: '/',
method: 'GET',
headers: {
'x-my-header': 'foo'
}
})

response.body.on('data', chunk => {
body.push(chunk)
})

await once(response.body, 'end')

t.strictEqual(response.statusCode, 200)
t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8')
t.strictEqual(response.headers['x-custom-h2'], 'hello')
t.strictEqual(Buffer.concat(body).toString('utf8'), 'hello h2!')

await t.completed
})
12 changes: 6 additions & 6 deletions test/http2-alpn.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,9 @@ test('Should upgrade to HTTP/2 when HTTPS/1 is available for GET', async (t) =>
}
)

server.listen(0)
await once(server, 'listening')

// close the server on teardown
after(() => server.close())
await once(server.listen(0), 'listening')

// set the port
const port = server.address().port
Expand Down Expand Up @@ -122,6 +120,8 @@ test('Should upgrade to HTTP/2 when HTTPS/1 is available for GET', async (t) =>
alpnProtocol: false,
httpVersion: '1.1'
}))

await t.completed
})

test('Should upgrade to HTTP/2 when HTTPS/1 is available for POST', async (t) => {
Expand Down Expand Up @@ -191,11 +191,9 @@ test('Should upgrade to HTTP/2 when HTTPS/1 is available for POST', async (t) =>
stream.end('hello h2!')
})

server.listen(0)
await once(server, 'listening')

// close the server on teardown
after(() => server.close())
await once(server.listen(0), 'listening')

// set the port
const port = server.address().port
Expand Down Expand Up @@ -275,4 +273,6 @@ test('Should upgrade to HTTP/2 when HTTPS/1 is available for POST', async (t) =>
t.equal(httpsResponse.headers['x-custom-alpn-protocol'], 'false')
t.equal(Buffer.concat(httpsResponseBody).toString('utf-8'), 'hello http/1!')
t.equal(Buffer.concat(httpsRequestChunks).toString('utf-8'), expectedBody)

await t.completed
})
Loading
Loading