binki / autoserve

Deploy a node webapp to FastCGI, Passenger, node http, or other things in the future
Other
1 stars 0 forks source link

Automatically adapt any http.createServer()-compatible service to any deployment platform.

One might deploy a node-based webapp to any of the following platforms:

But how do you support all these platforms at once? By using an abstraction layer such as autoserve!

Usage

To write an application, simply pass the function you would pass to http.createServer() to autoserve():

script.cgi:

#!/usr/bin/env node
'use strict';

const autoserve = require('autoserve');

const app = function (req, res) {
    res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8', });
    // It is recommended to use a framework like express to calculate
    // the host and protocol of your deployment. baseUrl only
    // solves the path portion of the deployment.
    res.end(`Hello, World! I am deployed at https://${req.headers.host}${req.baseUrl}`);
};

autoserve(app);

That works OK for a very simple development server or with mod_fcgid, but doesn’t solve the issue of deploying to a highly specialized platform. If the above script is published as an npm module named example-autoserve-app, you can configure autoserve prior to require()ing your app’s module. This way, you can keep the deployment-specific configuration separate from your application logic:

index.cgi:

#!/usr/bin/env node
'use strict';

const autoserve = require('autoserve');

// Register a custom platform for the deployment
// environment.
autoserve.register({
    detect: () => true,
    name: 'annoying-http',
    priority: 100,
    serve: function (app, options) {
        require('http').createServer(app).listen(options.port, function () {
            require('child_process').exec(`:; xdg-open http://localhost:${options.port}/; exit $?\nSTART http://localhost:${options.port}/`);
        });
    },
});

// Override a registered platform’s property. Here
// we lower the core http platform’s priority so that
// our custom one will win (yes, this example is
// contrived).
autoserve.override('http', {
    priority: 99,
});

// Set options for this environment.
autoserve.extendOptions({
    'annoying-http': {
        port: 1025+1000*Math.random()|0,
    },
});

// The deployed app will see the configuration set
// above when it runs.
require('example-autoserve-app');

Express Usage

Express doesn’t seem to handle request.baseUrl being set. Use express-autoserve.

API

Module

The module is invokable and behaves the same as serve().

const autoserve = require('autoserve');

serve(app)

You normally call this by calling the module itself:

autoserve(function (request, response) {
    …
});

This is analogous to the following snippet which directly uses the http module. In fact, when the http platform is chosen by detect(), it will be equivalent.

const http = require('http');
http.createServer(function (request, response) {
    …
}).listen(3000);

The parameters request and response shall mimic the behavior of the equivalent http module-provided objects. However, many platforms other than http will only support a subset of operations. An application wishing to be portable can assume that the following APIs are present:

Many platforms strive to provide undocumented and unmentioned APIs on request and response to support popular frameworks such as Express.

autoserve also defines the following properties: