Узел HTTP2: возможно ли несколько сообщений между клиентом и сервером, использующими один и тот же поток? - PullRequest
1 голос
/ 13 апреля 2020

Узел и 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 не поддерживает запись клиента дважды в один и тот же поток

1 Ответ

0 голосов
/ 23 апреля 2020

Да, однако, заголовок может быть отправлен только один раз, а не для каждого сообщения!

Обновленный код сервера:

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)
...