TrevTheDev
TrevTheDev

Reputation: 2737

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

Node and HTTP2 allow the server to provide multiple responses to a client. But what if the client wants to send an initial request and after the server responds the client wants to send a further message? One solution would be to create a new request - but that seems to negate the benefit of a duplex stream.

Simple server code:

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)

Test client code:

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()
    })
  })
})

Produces ERR_HTTP2_STREAM_ERROR cause I assume Node doesn't support the client writing twice to the same stream?

Upvotes: 2

Views: 892

Answers (1)

TrevTheDev
TrevTheDev

Reputation: 2737

Yes it is, however, the header can only be sent once and not for each communication!

Updated server code:

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)

Upvotes: 1

Related Questions