https://github.com/binki/autoserve
Deploy a node webapp to FastCGI, Passenger, node http, or other things in the future
https://github.com/binki/autoserve
Last synced: about 1 year ago
JSON representation
Deploy a node webapp to FastCGI, Passenger, node http, or other things in the future
- Host: GitHub
- URL: https://github.com/binki/autoserve
- Owner: binki
- License: other
- Created: 2016-08-23T05:48:59.000Z (almost 10 years ago)
- Default Branch: master
- Last Pushed: 2016-09-30T05:41:11.000Z (over 9 years ago)
- Last Synced: 2025-03-12T01:26:46.349Z (over 1 year ago)
- Language: JavaScript
- Size: 47.9 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
Automatically adapt any `http.createServer()`-compatible service to
any deployment platform.
One might deploy a node-based webapp to any of the following
platforms:
* [`http`](https://nodejs.org/api/http.html)
* [`node-fastcgi`](https://github.com/fbbdev/node-fastcgi)
* Phusion Passenger
* Custom Platform (see docs below)
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](https://github.com/binki/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`](https://nodejs.org/api/http.html) 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`](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
and
[`response`](https://nodejs.org/api/http.html#http_class_http_serverresponse)
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:
* `request`
* [`headers`](https://nodejs.org/api/http.html#http_message_headers)
* [`method`](https://nodejs.org/api/http.html#http_message_method)
* [`url`](https://nodejs.org/api/http.html#http_message_url)
* `response`
* [`end`](https://nodejs.org/api/http.html#http_response_end_data_encoding_callback)
* [`write`](https://nodejs.org/api/http.html#http_response_write_chunk_encoding_callback) (though the platform might buffer everything instead of streaming chunks).
* [`writeHead`](https://nodejs.org/api/http.html#http_response_writehead_statuscode_statusmessage_headers)
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:
* `request`
* `baseUrl`: The URI used to access the script. This is useful for
applications which want to generate fully qualified internal links
which is useful when issuing redirects (the [HTTP `Location:`
header](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.30)
requires fully qualified URIs).
Note that the URI provided here excludes host and protocol
fields—it will begin with a `/`. In fact, it will behave quite
like [Express’s `req.baseUrl`
property](https://expressjs.com/en/4x/api.html#req.baseUrl).
The `http` module does not provide this property because it
doesn’t support mounting applications at anything other than
`/`. However, in many deployment scenarios, an application will be
made accessible as a subtree of a host. This might be accomplished
using rewrites/aliases or implicitly based on the application’s
position in the filesystem hierarchy.
For example, Apache’s `mod_fcgid` might be configured as follows.
This would result in
[`autoserve-platform-node-fastcgi`](https://github.com/binki/autoserve-platform-node-fastcgi)
being detected and used:
# FilesMatch is more secure (exhibiting less confusing behavior) than AddHandler.
SetHandler fcgid-script
Options +ExecCGI
And a request might come in for
`/some/path/script.cgi/sub/resource`. In this case, `baseUrl` will
be `/some/path/script.cgi` while `url` will be
`/some/path/script.cgi/sub/resource`. Thus, `baseUrl` is
implicitly calculated by where the script is placed in the
filesystem. If you had a `RewriteRule` or `Alias` that runs
`script.cgi` when `/some/path/` is accessed, the `baseUrl` would
be explicitly set to the aliased path.