节点 HTTP2:客户端和服务器之间是否可以使用相同的流发送多条消息?

Node HTTP2: is multiple messages between client and server using the same stream possible?

Node 和 HTTP2 允许服务器向客户端提供多个响应。但是,如果客户端想要发送初始请求并且在服务器响应之后客户端想要发送进一步的消息怎么办?一种解决方案是创建一个新请求——但这似乎抵消了双工流的好处。

简单服务器代码:

import http2 from 'http2'

const options = {
  key: fs.readFileSync('./dev certificate/selfsigned.key'),
  cert: fs.readFileSync('./dev certificate/selfsigned.crt'),
}

const server = http2.createSecureServer()

server.on('stream', (stream, headers) => {
  stream.on('data', (chunk) => {
    console.log(`server: ${chunk.toString()}`)
    stream.respond({
      'content-type': 'application/json',
      ':status': 200
    })
    stream.write(chunk) // echo message received
  })
})

server.listen(8443)

测试客户端代码:

import http2 from 'http2'

describe('http2 messaging test', () => {
  it('http2 messaging', (done) => {
    const client = http2.connect('https://localhost:8443', {
      rejectUnauthorized: false,
    })
    const msg1 = 'message 1'

    const stream = client.request({
      ':method': 'POST',
      ':path': '/',
      'Content-Type': 'text/plain',
      'Content-Length': msg1.length,
    })

    stream.on('response', async (headers, flags) => {
      stream.write('next message') // send the next message after response to first one
                                   // server doesn't receive this
    })

    stream.write(msg1)

    stream.on('data', (chunk) => {
      console.log(`client: ${chunk.toString()}`)
      if (chunk.toString() === 'next message') done()
    })
  })
})

产生 ERR_HTTP2_STREAM_ERROR 因为我认为 Node 不支持客户端向同一个流写入两次?

是的,但是,header只能发送一次,而不是每次通信!

更新的服务器代码:

import http2 from 'http2'

const options = {
  key: fs.readFileSync('./dev certificate/selfsigned.key'),
  cert: fs.readFileSync('./dev certificate/selfsigned.crt'),
}

const server = http2.createSecureServer()

server.on('stream', (stream, headers) => {
  stream.respond({   // Headers is now only sent once when the stream is connected!
    'content-type': 'application/json',
    ':status': 200
  })
  stream.on('data', (chunk) => {
    console.log(`server: ${chunk.toString()}`)
    stream.write(chunk) // echo message received
  })
})

server.listen(8443)