Search code examples
node.jsstreamhttp2node-streams

Sending and receiving JSON in Node HTTP2 streams


I'm working on building an authentication microservice in Node using HTTP2.

How do I properly write JSON to and read it from Node HTTP2 streams?

The documentation gives these examples:

const http2 = require('http2');
const fs = require('fs');

const server = http2.createSecureServer({
  key: fs.readFileSync('localhost-privkey.pem'),
  cert: fs.readFileSync('localhost-cert.pem')
});
server.on('error', (err) => console.error(err));

server.on('stream', (stream, headers) => {
  // stream is a Duplex
  stream.respond({
    'content-type': 'text/html',
    ':status': 200
  });
  stream.end('<h1>Hello World</h1>');
});

server.listen(8443);

and

const http2 = require('http2');
const fs = require('fs');
const client = http2.connect('https://localhost:8443', {
  ca: fs.readFileSync('localhost-cert.pem')
});
client.on('error', (err) => console.error(err));

const req = client.request({ ':path': '/' });

req.on('response', (headers, flags) => {
  for (const name in headers) {
    console.log(`${name}: ${headers[name]}`);
  }
});

req.setEncoding('utf8');
let data = '';
req.on('data', (chunk) => { data += chunk; });
req.on('end', () => {
  console.log(`\n${data}`);
  client.close();
});
req.end();

Let's say I have a JSON object which I want to write to the stream in the client and read from the stream in the server, and vice versa. How do I do this properly?

I can stringify my JSON to str and use request.write(str, 'utf-8), but is that the optimal way? And how do I listen for the JSON on the other side in order to handle it?


Solution

  • The server...

    
    const http2 = require('http2');
    const fs = require('fs');
    
    const server = http2.createSecureServer({
      key: fs.readFileSync('localhost-privkey.pem'),
      cert: fs.readFileSync('localhost-cert.pem')
    });
    
    server.on('error', (err) => {
      console.error(err)
    });
    
    server.on('stream', (stream, headers) => {
      // stream is a Duplex
      
      // headers[:path] is the normal request from browser. A path url.
    
      console.log("Request from client: " + headers[:path]);
      
    
      req.on("data", (data) => {
        console.log("Data from HTTPS2 client(event): " + data);
        // It is just the data from 'POST' method.
      });
    
    
    
    stream.respond({
        'content-type': 'text/html',
        ':status': 200
      });
    
      stream.end('<h1>Hello World</h1> Or a string, other data, wherever you want...');
    
    });
    
    server.listen(8443);
    

    The Client. Can be a XHR request in 'GET' or 'POST' method. Server side is the same. To 'GET' mode use method = GET and remove "req.end('XXX any string. bla, bla, bla');"

    const http2 = require('http2');
    const fs = require('fs');
    
    
    const client = http2.connect('https://localhost:8443', {
      ca: fs.readFileSync('localhost-cert.pem')
    });
    
    
    client.on('error', (err) => {
      console.error(err)
    });
    
    //':method': 'GET/POST' Can be just one.
    const req = client.request({ ':method': 'POST', ':path': '/' });
    
    req.on('response', (headers, flags) => {
      for (const name in headers) {
        console.log(`${name}: ${headers[name]}`);
      }
    });
    
    req.setEncoding('utf8');
    let data = '';
    
    //Data from HTTPS2 server.
    req.on('data', (chunk) => { 
    
      data += chunk; 
    
    });
    
    req.on('end', () => {
      console.log(`\n${data}`);
      client.close();
    });
    
    //Only for POST method.
    req.end("The data you want to send. String, JSON, buffer whatever...");