Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust Websocket-over-HTTP example to work out of the box #35

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 30 additions & 10 deletions samples/websocket-over-http.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ const {
Publisher,
} = require('@fanoutio/grip');

const PUBLISHER = new Publisher({
'control_uri': 'http://localhost:5561',
});

const CHANNEL = 'all';

http.createServer(async (req, res) => {
// Validate the Grip-Sig header:
if (!validateSig(req.headers['grip-sig'], 'changeme')) {
Expand All @@ -27,6 +33,15 @@ http.createServer(async (req, res) => {
return;
}

let responseBody;

// Manually set headers to accept Websocket-over-HTTP
res.setHeader('Content-Type', 'application/websocket-events');
res.setHeader('Sec-WebSocket-Extensions', 'grip');

// This header causes issues with Node v20.8.1 — wscat hangs and disconnects in 5 seconds
res.removeHeader("Transfer-Encoding");

const inEventsEncoded = await new Promise(resolve => {
let body = '';
req.on('data', function (chunk) {
Expand All @@ -43,30 +58,35 @@ http.createServer(async (req, res) => {
if (wsContext.isOpening()) {
// Open the WebSocket and subscribe it to a channel:
wsContext.accept();
wsContext.subscribe('<channel>');

// This adds a control messsage to output that goes to client (?)
wsContext.subscribe(CHANNEL);
// It doesn't work without it
res.setHeader('Grip-Channel', CHANNEL);

// The above commands made to the wsContext are buffered
// in the wsContext as "outgoing events".
// Obtain them and write them to the response.
const outEvents = wsContext.getOutgoingEvents();
const outEventsEncoded = encodeWebSocketEvents(outEvents);
res.write(outEventsEncoded);
responseBody = outEventsEncoded;

// As an example way to check our subscription, wait and then
// publish a message to the subscribed channel:
setTimeout(() => {
var publisher = new Publisher({
'control_uri': '<myendpoint>',
});
publisher.publishFormats(
'<channel>',
new WebSocketMessageFormat('Test WebSocket Publish!!')
);
PUBLISHER.publishFormats(CHANNEL, new WebSocketMessageFormat('Test WebSocket Publish!!'));
}, 5000);
} else {
// Here we emulate some sort of echoing to demonstrate
// how an origin could react to incoming websocket messages
const [command, payload] = inEventsEncoded.split("\n").map(s => s.trim());
const messageToClient = JSON.stringify({command, payload});
PUBLISHER.publishFormats(CHANNEL, new WebSocketMessageFormat(messageToClient));
}

// Set the headers required by the GRIP proxy:
res.writeHead(200, wsContext.toHeaders());
res.writeHead(200);
if (responseBody) { res.write(responseBody) };
res.end();

}).listen(80, '0.0.0.0');
Expand Down