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

Request gets stuck when doing POST using http2 #2335

Closed
binsee opened this issue Oct 11, 2023 · 0 comments · Fixed by #2336
Closed

Request gets stuck when doing POST using http2 #2335

binsee opened this issue Oct 11, 2023 · 0 comments · Fixed by #2336
Labels
bug Something isn't working

Comments

@binsee
Copy link
Contributor

binsee commented Oct 11, 2023

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
@binsee binsee added the bug Something isn't working label Oct 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant