Fishback is a simple NodeJS-powered caching HTTP proxy.
As well as supporting different caching backends, the design lends itself to
filtering and processing the headers of both requests and responses. (For
example, changing Cache-Control
headers.) It is not well-suited to
transforming request or response bodies, though it can be integrated into
systems that do provide this feature.
Fishback tries hard to be RFC2616 compliant (and many of the slightly unusual
features like only-if-cached
and max-stale
are supported), but there's
probably some things it doesn't do completely correctly. (Though any variation
from RFC2616 should be considered a bug.)
var fishback = require("../lib/fishback");
var http = require("http");
var proxy = fishback.createProxy(new fishback.Client("localhost", 9000));
proxy.on("newRequest", function (req) {
console.log(req.method + " " + req.url);
});
proxy.on("newResponse", function (res) {
res.setHeader("cache-control", "public, max-age=3600");
});
http.createServer(proxy.request.bind(proxy)).listen(8000);
console.log("Listening on port 8000, and proxying to localhost:9000");
For more, see the examples directory.
$ npm install fishback
Fishback is heavily event based, and it relies heavily on the four event
emitters http.ServerRequest
, http.ServerResponse
, http.ClientRequest
and
http.ClientResponse
.
In contrast to most NodeJS "middleware" systems (including
Connect), Fishback itself does not contain
a web server. Instead, Fishback provides a handler for http.Server's
'request' event.
fishback.Handler
client
- probably afishback.Client
Convenience function for creating a simple proxy from a client.
fishback.Handler
cache
- probably one of the cache backendsfishback.Handler
client
- probably afishback.Client
Convenience function for creating a proxy from a cache and client.
"Abstract" base class for all handlers. All the classes below (the HTTP client that does real requests, the various cache backends, and the Fishback class that ties them together) are derived from this class.
function (serverRequest) { }
http.ServerRequest
serverRequest
Emitted when a new request has been received. (At the point the event is emitted, only headers are available, though you can of course arrange to listen to other events.)
function (serverResponse) { }
http.ServerResponse
serverResponse
Emitted when a new response is being sent. (At the point the event is emitted,
only headers are available. Because of limitations in the
http.ServerResponse
API (write()
does not fire any events), it is not possible to observe any
"write" events.)
http.ServerRequest
serverRequest
http.ServerResponse
serverResponse
Processes a request/response pair.
If unable to handle the request (e.g. resource is not cached), serverRequest
will emit the reject
event.
If request is accepted (i.e. the handler is writing to serverResponse
),
serverResponse
will emit the endHead
event when headers have been set on the
response.
(If overriding this method, note that the handler must ensure that if a request
is rejected, any handlers that may subsequently be invoked are actually able to
fulfill the request! The most important implication of this constraint is that
if the request method is not GET
, it must be rejected immediately
(synchronously). If the method is GET
, the request can be rejected
asynchronously since subsequent handlers do not need any information from data
events they would otherwise have missed).)
http.ClientResponse
clientResponse
Process a client response.
This is really only useful for caching handlers--it allows them to populate their caches from responses to any real HTTP requests that are issued.
(For example, fishback.createCachingProxy()
arranges things so that if the
cache handler fires a reject
event, a "real" HTTP request to be issued; the
response from this request is then passed to the cache.)
Derived from fishback.Handler
.
list
an array offishback.Handler
objects
The last object in list is assumed to be a real HTTP client that will never
reject
a request. The other objects can reject requests.
Derived from fishback.Handler
.
backend_hostname
- e.g. 'localhost'backend_port
- e.g. 80http
- object with arequest()
method, such asrequire('http')
Does a real HTTP request.
Derived from fishback.Handler
.
Caching backend.
Derived from fishback.Handler
.
- There's no HTTPS support.
- If the proxy server is able to read from the origin faster than the client
can receive data, content needs to be buffered, either by node or the
kernel. (This can be fixed by backing off when
write()
returns false, and resuming only when the "drain" event is triggered. This is only likely to be a problem if you're streaming very large files through node.) - ETags (and
must-revalidate
) are not supported. (You don't get incorrect results; you just need retrieve the entire resource from the origin each time.)
If you're only after a proxy (rather than a caching proxy), node-http-proxy may be more suitable.
Michael Stillwell mjs@beebo.org