Skip to content
Michael Schwartz edited this page Jun 20, 2014 · 2 revisions

SilkJS + HTTPD

SilkJS comes with an HTTP server written almost entirely in JavaScript. It can be found in the httpd/ directory in the repository.

To run the server:

./SilkJS httpd/main.js [optional additional .js files]

Once it's running, you can point your browser at http://localhost:9090/ and see it in action.

config.js

The server reads its configuration information from config.js in the httpd directory. You can provide your own config.js by passing it as an additional .js file on the command line.

// httpd/config.js
Config = {
	port: 9090,
	numChildren: 250,
	requestsPerChild: 100000,
	documentRoot: fs.exists('httpd/docroot') ? 'httpd/docroot' : '/usr/share/SilkJS/httpd/docroot',
//	mysql: {
//		host: 'localhost',
//		user: 'mschwartz',
//		passwd: '',
//		db: 'sim'
//	},
	lockFile: '/tmp/silkf.lock'
};

The members are as follows:

port specifies the port that the server listens on. In production, this would be 80.

numChildren specifies the number of child processes the server will pre-fork and maintain. When a child exits for any reason, the main() function will spawn a new one.

requestsPerChild specifies how many requests each child will handle before exiting. If you're paranoid, set this to a low number like 100.

documentRoot specifies the document root of your WWW site. Static files, .jst files, .md files, etc., will be served from this directory.

mysql (optional) is an object that specifies MySQL connection parameters. If present, each child will initially create a connection to MySQL using these parameters. This connection can be reused by your application in that child process. The members are host: 'hostname', user: 'username', passwd: 'password', db: 'database_name'.

lockFile is the full path to a file that HTTP will use to lock around accept() calls in the child. This locking addresses the well-known (maybe not so publicized) thundering herd issue. On Ubuntu, this could be in /dev/shm/somefilename which is RAM disk.

Extending HTTP

HTTP is meant to be extensible without modifying the actual source code, though modifying the source code is not frowned upon.

If you specify additional .js files on the command line, those are loaded and you can do whatever you want in those scripts.

If your script sets HttpChild.requestHandler to a function, that function will be called to handle each request. Your requestHandler() function has access to the global req and res objects. If your requestHandler() returns, the regular HTTP request handler logic is run. If your requestHandler() calls res.stop(), the regular regular logic will not run.

Your additional .js files may provide functions of the form:

function foo_action() {
 ...
}

The regular HTTP logic will call your foo_action() if the URI requested is /foo or /foo/anything... Similarly, if you provide a bar_action() and the request is /bar or /bar/anything..., that function will be called. If you provide a main_action(), it will be called if the request is /.

These functions have access to the global req and res objects and may call res.stop() to prevent the regular request logic from running.

The child.js file has a hash variable called contentTypes that maps file extensions to content type (mime type) and a handler to serve those types. Feel free to add more types to this hash and handler functions to the HttpChild singleton. I'll figure out a better way to extend this at some point :)

Clone this wiki locally