NOTE: express-grip is no longer maintained. It has been superseded completely by connect-grip.
connect-grip
is a new library that is fully connect
-compatible, and works
with additional frameworks including Next.js.
Additionally, its improved architecture avoids the need to use a pre- and
post-middleware, allowing routes to be written in a more standard way and other
middleware to work more reliably.
Author: Konstantin Bokarius kon@fanout.io, Katsuyuki Ohmuro harmony7@pex2.jp
An Express GRIP library.
This library is compatible with Express 4.x, and may work with Express 3.x as well.
npm install @fanoutio/express-grip
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({
/* config */
});
// Add the pre-handler middleware to the front of the stack
router.use( expressGrip.preGrip );
// .. routes
// Add the post-handler middleware to the back of the stack
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.
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:
// Pushpin and/or Fanout.io is used for sending realtime data to clients
const expressGrip = buildExpressGrip({
gripProxies: [
// Pushpin
{
'control_uri': 'http://localhost:5561',
'key': 'changeme',
},
// Fanout.io
{
'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'
},
],
});
import express from 'express';
import { HttpStreamFormat } from '@fanoutio/grip';
import buildExpressGrip, { setHoldStream, } from '@fanoutio/express-grip';
const app = express();
// GRIP will publish to local Pushpin
const expressGrip = buildExpressGrip({
gripProxies: [{
control_uri: "http://localhost:5561/",
}],
});
// Add the pre-handler middleware to the front of the stack
app.use(expressGrip.preGrip);
app.get('/', function(req, res, next) {
try {
// Subscribe every incoming request to a channel in stream mode
// 'test' is the channel name
setHoldStream(res, 'test');
res.send('[stream open]\n');
} finally {
// next() must be called for the post-handler middleware to execute
next();
}
});
app.post('/', function(req, res, next) {
const data = req.body;
// Publish stream data to subscribers
// 'test' is the channel name
expressGrip.publish('test', new HttpStreamFormat(data + '\n'));
res.send('Ok\n');
next();
});
// Add the post-handler middleware to the back of the stack
app.use(expressGrip.postGrip);
The CommonJS version of this package requires Node v8 or newer.
Require in your JavaScript:
const buildExpressGrip = require('@fanoutio/express-grip');
const expressGrip = buildExpressGrip({ /* config */ });
If you are building a bundle, you may also import in your JavaScript.
import grip from '@fanoutio/express-grip';
const expressGrip = buildExpressGrip({ /* config */ });
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({ /* config */ });
// IGripExpressResponse is a type declaration.
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
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.
(C) 2015, 2020 Fanout, Inc.
Licensed under the MIT License, see file LICENSE for details.