N.A.P.
N.A.P.

Reputation: 57

Listening for HTTP traffic on master process, handling connections on child process?

I'm looking for a way to have a socket listening for HTTP requests on a master process, then passing any incoming connections and the request data to a child process using process.send() and handling the HTTP request in the child process.

However, I'm unable to find a way to attach the passed connection and the request data to a HTTP server in the child process, without initializing the server by .listen()ing on a socket.

So, is it somehow possible to use a HTTP server to handle a connection passed in from another process? Any non-public API solution will also do (hopefully JavaScript-side, though).

I guess I could initialize the server to listen on some dummy socket and then bounce the incoming connections off of that, but that would seem suboptimal. Passing in the listening socket as well or using Cluster or a reverse proxy would also not be optimal in my case.

Upvotes: 3

Views: 1275

Answers (1)

Laurent Perrin
Laurent Perrin

Reputation: 14881

It is possible, but first you need to get some understanding of how node.js works:

  • A TCP server (from net.createServer) is basically an EventEmitter which only emits connection events.

  • An HTTP server (from http.createServer) is a TCP server with a connection parser.

Unfortunately for you, the HTTP server is hardwired to a TCP server (see source):

function Server(requestListener) {
  if (!(this instanceof Server)) return new Server(requestListener);
  net.Server.call(this, { allowHalfOpen: true });

  ...

  this.addListener('connection', connectionListener);

  ...
}

What you need is to pass your socket to connectionListener which is defined in http.js. The good news is that the module exports it:

exports._connectionListener = connectionListener;

I haven't tried this code, but it should work with some tweaks:

var util = require('util'),
    events = require('events'),
    http = require('http'),
    express = require('express'),
    app = express();

function FakeServer() {
  events.EventEmitter.call(this);

  this.on('connection', http._connectionListener);
  this.on('request', app);
}

util.inherits(FakeServer, events.EventEmitter);

var server = new FakeServer();

process.on('message', function ('socket', socket) {
  server.emit('connection', socket);
});

// you can use app as a regular express app
app.get('/hello', function (req, res) {
  res.send('world');
};

Upvotes: 3

Related Questions