express-grip
Author: Konstantin Bokarius kon@fanout.io, Katsuyuki Ohmuro harmony7@pex2.jp
An Express GRIP library.
Installation
This library is compatible with Express 4.x, and may work with Express 3.x as well.
npm install @fanoutio/express-grip
Usage
Architecture
This library provides two middleware classes.
This library is able to perform its magic and provide conveniences through the use of
both pre-route and post-route middleware. Therefore, in order to use this library you
must use
both of them.
import buildExpressGrip from '@fanoutio/express-grip';
const expressGrip = buildExpressGrip({
});
router.use( expressGrip.preGrip );
router.use( expressGrip.postGrip );
Therefore, even if a particular route does not use express-grip
features, it's necessary
to call next() at the end of each of your route handlers to ensure that the post-route middleware
executes.
The two middleware classes will work together to parse the Grip-Sig header in any requests to detect
if they came from a GRIP proxy, and it will apply any hold instructions when responding. Additionally,
the middleware handles WebSocket-Over-HTTP processing so that WebSockets managed by the GRIP
proxy can be controlled via HTTP responses from the Express application.
Configuration
Configure express-grip by passing options to the buildExpressGrip
function.
import buildExpressGrip from '@fanoutio/express-grip';
const expressGrip = buildExpressGrip({
});
Set gripProxies
for GRIP proxy validation and publishing:
const expressGrip = buildExpressGrip({
gripProxies: [
{
'control_uri': 'http://localhost:5561',
'key': 'changeme',
},
{
'control_uri': 'https://api.fanout.io/realm/your-realm',
'control_iss': 'your-realm',
'key': Base64.decode64('your-realm-key'),
},
],
});
If it's possible for clients to access the Express app directly, without necessarily
going through the GRIP proxy, then you may want to avoid sending GRIP instructions
to those clients. An easy way to achieve this is with the gripProxyRequired
setting.
If set, then any direct requests that trigger a GRIP instruction response will be
given a 501 Not Implemented error instead.
const expressGrip = buildExpressGrip({
gripProxyRequired: true,
});
To prepend a fixed string to all channels used for publishing and subscribing, set
gripPrefix
in your configuration:
const expressGrip = buildExpressGrip({
gripPrefix: '<prefix>',
});
You can also set any other EPCP servers that aren't necessarily proxies with
publishServers
:
const expressGrip = buildExpressGrip({
gripPubServers: [
{
'uri': 'http://example.com/base-uri',
'iss': 'your-iss',
'key': 'your-key'
},
],
});
Sample Usage
import express from 'express';
import { HttpStreamFormat } from '@fanoutio/grip';
import buildExpressGrip, { setHoldStream, } from '@fanoutio/express-grip';
const app = express();
const expressGrip = buildExpressGrip({
gripProxies: [{
control_uri: "http://localhost:5561/",
}],
});
app.use(expressGrip.preGrip);
app.get('/', function(req, res, next) {
try {
setHoldStream(res, 'test');
res.send('[stream open]\n');
} finally {
next();
}
});
app.post('/', function(req, res, next) {
const data = req.body;
expressGrip.publish('test', new HttpStreamFormat(data + '\n'));
res.send('Ok\n');
next();
});
app.use(expressGrip.postGrip);
Consuming this library
CommonJS
The CommonJS version of this package requires Node v8 or newer.
Require in your JavaScript:
const buildExpressGrip = require('@fanoutio/express-grip');
const expressGrip = buildExpressGrip({ });
If you are building a bundle, you may also import in your JavaScript.
import grip from '@fanoutio/express-grip';
const expressGrip = buildExpressGrip({ });
This package comes with full TypeScript type definitions, so you may use it with
TypeScript as well.
import buildExpressGrip, { IGripExpressResponse } from '@fanoutio/express-grip';
const expressGrip = buildExpressGrip({ });
Demos
HTTP Demo
Express 4 Grip Hold Stream example.
- Clone this repository, then build the commonjs build of this library.
npm install
npm run build-commonjs
- You will need to obtain and install Pushpin (https://pushpin.org/). Make sure that the Pushpin
routes
file looks like this:
* localhost:3000
- In a Terminal window, start Pushpin.
pushpin
- In another Terminal window, start the demo server.
cd demo/http
node server.js test
- In another Terminal window, issue an HTTP long poll.
curl -i http://localhost:7999/
- Finally, in another Terminal window, post a message.
curl -i -X POST -d 'foo' http://localhost:7999/
- In the Terminal window from step 5, you will see the message appear.
The same example is also provided in Typescript. In place of step 3 above,
use the TypeScript version:
cd demo/http-typescript
ts-node server.ts test
Websocket Demo
Express 4 stateless WebSocket echo service example with broadcast endpoint.
- Clone this repository, then build the commonjs build of this library.
npm install
npm run build-commonjs
- You will need to obtain and install Pushpin (https://pushpin.org/). Make sure that the Pushpin
routes
file looks like this:
* localhost:3000,over_http
- In a Terminal window, start Pushpin.
pushpin
- In another Terminal window, start the demo server.
cd demo/ws
node server.js test
- In another Terminal window, open a Websocket connection.
wscat --connect ws://localhost:7999/websocket
- Finally, in another Terminal window, post a message.
curl -i -X POST -d 'foo' http://localhost:7999/broadcast
- In the Terminal window from step 5, you will see the message appear.
License
(C) 2015, 2020 Fanout, Inc.
Licensed under the MIT License, see file LICENSE for details.