Skip to content

Request gets stuck when doing POST using http2 #2335

@binsee

Description

@binsee

Bug Description

When using http2 for POST, if body is string or Buffer, the request will get stuck. This works fine if body is a stream

Reproducible By

test code:

test('Should support H2 connection(POST Buffer)', async t => {
  const server = createSecureServer({ ...pem, allowHTTP1: false })

  server.on('stream', async (stream, headers, _flags, rawHeaders) => {
    t.equal(headers[':method'], 'POST')
    const reqData = []
    stream.on('data', chunk => reqData.push(chunk.toString()))
    await once(stream, 'end')
    const reqBody = reqData.join('')
    t.equal(reqBody.length > 0, true)
    stream.respond({
      'content-type': 'text/plain; charset=utf-8',
      'x-custom-h2': 'hello',
      ':status': 200
    })
    stream.end(`hello h2! ${reqBody}`)
  })

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

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

  t.plan(6)
  t.teardown(server.close.bind(server))
  t.teardown(client.close.bind(client))

  const sendBody = `hello!`
  const body = []
  console.log(`before request ${sendBody}`)
  const response = await client.request({
    path: '/',
    method: 'POST',
    // FIXME: If send a Buffer or string, the stream will not end, causing it to get stuck.
    body: sendBody
  })
  console.log(`after request ${sendBody}`)

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

  await once(response.body, 'end')
  t.equal(response.statusCode, 200)
  t.equal(response.headers['content-type'], 'text/plain; charset=utf-8')
  t.equal(response.headers['x-custom-h2'], 'hello')
  t.equal(Buffer.concat(body).toString('utf8'), `hello h2! ${sendBody}`)
})

Expected Behavior

Logs & Screenshots

image

image

Environment

  • MacOS 14.0
  • Nodejs 16.19.0
  • undici 5.25.4

Additional context

Maybe we can fix this by:

  • Added call to stream.end() in writeBodyH2 ()
  • Use Readable.from(body) in writeBodyH2 () to convert body to a readable stream

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions