Skip to content

Instantly share code, notes, and snippets.

@ugultopu
Last active October 19, 2020 18:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ugultopu/fe6eb13408bbc6a9b1da697f4d30395e to your computer and use it in GitHub Desktop.
Save ugultopu/fe6eb13408bbc6a9b1da697f4d30395e to your computer and use it in GitHub Desktop.
Simply using the Server constructor function is enough

AFAICT, createServer function is being kept only for compatibility, because all it does now is to simply call the Server constructor as is:

In http module:

function createServer(opts, requestListener) {
  return new Server(opts, requestListener);
}

Hence, we can simply use:

const { Server } = require('http');

const server = new Server((req, res) => res.end('Hello!'));

In fact, if we examine where Server is defined by scrolling on top of http:

const {
  _connectionListener,
  STATUS_CODES,
  Server,
  ServerResponse
} = require('_http_server');

We understand that Server is coming from _http_server. Examining how Server is defined in _http_server:

function Server(options, requestListener) {
  if (!(this instanceof Server)) return new Server(options, requestListener);

  if (typeof options === 'function') {
    requestListener = options;
    options = {};
  } else if (options == null || typeof options === 'object') {
    options = { ...options };
  } else {
    throw new ERR_INVALID_ARG_TYPE('options', 'object', options);
  }

  this[kIncomingMessage] = options.IncomingMessage || IncomingMessage;
  this[kServerResponse] = options.ServerResponse || ServerResponse;

  const maxHeaderSize = options.maxHeaderSize;
  if (maxHeaderSize !== undefined)
    validateInteger(maxHeaderSize, 'maxHeaderSize', 0);
  this.maxHeaderSize = maxHeaderSize;

  const insecureHTTPParser = options.insecureHTTPParser;
  if (insecureHTTPParser !== undefined)
    validateBoolean(insecureHTTPParser, 'options.insecureHTTPParser');
  this.insecureHTTPParser = insecureHTTPParser;

  net.Server.call(this, { allowHalfOpen: true });

  if (requestListener) {
    this.on('request', requestListener);
  }

  // Similar option to this. Too lazy to write my own docs.
  // http://www.squid-cache.org/Doc/config/half_closed_clients/
  // https://wiki.squid-cache.org/SquidFaq/InnerWorkings#What_is_a_half-closed_filedescriptor.3F
  this.httpAllowHalfOpen = false;

  this.on('connection', connectionListener);

  this.timeout = 0;
  this.keepAliveTimeout = 5000;
  this.maxHeadersCount = null;
  this.headersTimeout = 60 * 1000; // 60 seconds
  this.requestTimeout = 0;
}

We notice the line:

if (!(this instanceof Server)) return new Server(options, requestListener);

at the beginning of the Server function. This means that we can simply omit the new keyword when we are calling the Server constructor. Hence, we can simply use:

require('http').Server((req, res) => res.end('Hello!')).listen(3000, 'localhost');

as a basic server code. Expressed less tersely:

const { Server } = require('http');

const server = Server((req, res) => res.end('Hello!'));
server.listen(3000, 'localhost');

As another note, observe that if the first argument passed to Server function is a function (which is the case when only a single argument is passed), then Server treats this as the event handler for the request event. Or, if two arguments are passed, the second argument is the listener for the request event:

  if (requestListener) {
    this.on('request', requestListener);
  }

If we want to be more explicit, we can create a server as follows:

const { Server } = require('http');

const server = Server();
server.on('request', (req, res) => res.end('Hello!'));
server.listen(3000, 'localhost');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment