Skip to content

Commit

Permalink
debug: prod environment for websockets
Browse files Browse the repository at this point in the history
  • Loading branch information
chmanie committed Apr 17, 2024
1 parent 1b8da32 commit 48e9ecc
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 46 deletions.
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { handleWsUpgrade } from './routes/graphql/ws';

dotenv.config();

console.log(`Running in ${process.env.NODE_ENV} mode`);

const port = process.env.DEFAULT_PORT || 3005;
const proxy = proxyServerInstance();

Expand Down
102 changes: 56 additions & 46 deletions src/routes/graphql/ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ import WebSocket from 'ws';

import { logger } from '~helpers';

// The host of the AppSync API (non-realtime)
const WS_HOST = new URL('/', process.env.APPSYNC_API).host;
// In production the Amplify WebSocket API is secure and requires a different endpoint
const PROTOCOL = process.env.NODE_ENV === 'dev' ? 'ws' : 'wss';
const WS_ENDPOINT = process.env.NODE_ENV === 'dev' ? process.env.APPSYNC_API : process.env.APPSYNC_WSS_API;
const WS_HOST = new URL('/', WS_ENDPOINT).host;
const WS_ENDPOINT = process.env.NODE_ENV === 'dev' ? `ws://${WS_HOST}` : process.env.APPSYNC_WSS_API;

const wss = new WebSocket.Server({ noServer: true });

// Custom websocker upgrade handler
// This proxies websocket requests and adds the necessary headers for Amplify authorization if applicable
export const handleWsUpgrade = (req: InstanceType<typeof IncomingMessage>, socket: Duplex, head: Buffer) => {
const url = new URL(req.url || '', WS_ENDPOINT);
const url = new URL(req.url || '', 'http://localhost');
const authHeaders = {
host: WS_HOST,
// Creates a date in the format YYYYMMDDTHHMMSSZ
Expand All @@ -24,50 +24,60 @@ export const handleWsUpgrade = (req: InstanceType<typeof IncomingMessage>, socke
// Add "header" query string parameter (default is {})
url.searchParams.set('header', btoa((JSON.stringify(authHeaders))));
const proxyPath = `${url.pathname}?${url.searchParams.toString()}`
// FIXME: Remove
logger(`Connecting to ${WS_ENDPOINT}${proxyPath}`);
// Establish a websocket connection to Amplify
const targetWs = new WebSocket(`${PROTOCOL}://${WS_HOST}${proxyPath}`, 'graphql-ws', {
headers: {
'Sec-WebSocket-Version': req.headers['sec-websocket-version'],
'Sec-WebSocket-Key': req.headers['sec-websocket-key']
},
});
const targetWs = new WebSocket(`${WS_ENDPOINT}${proxyPath}`, 'graphql-ws');
targetWs.on('open', () => {
wss.handleUpgrade(req, socket, head, (ws) => {
// Add authorization headers to incoming client messages
ws.on('message', (data) => {
let parsed;
try {
parsed = JSON.parse(data.toString());
} catch (e) {
logger('Failed to parse websocket message', e);
return;
}
if (parsed.payload?.extensions?.authorization) {
parsed.payload.extensions.authorization = {
...parsed.payload.extensions.authorization,
...authHeaders,
};
return targetWs.send(JSON.stringify(parsed));
}
targetWs.send(data);
});
ws.on('close', () => {
targetWs.close();
});
ws.on('error', () => {
targetWs.close();
});

// Pass through messages from Amplify to the client
targetWs.on('message', (data) => {
ws.send(data.toString());
});
targetWs.on('close', () => {
ws.close();
});
targetWs.on('error', () => {
ws.close();
});
// FIXME: Remove
logger('WebSocket connection open to target');
targetWs.on('message', (data) => {
console.log(data.toString());
});
targetWs.send(JSON.stringify({ type: 'connection_init' }));
// wss.handleUpgrade(req, socket, head, (ws) => {
// // FIXME: Remove
// logger('WebSocket connection open to client');
// // Add authorization headers to incoming client messages
// ws.on('message', (data) => {
// let parsed;
// try {
// parsed = JSON.parse(data.toString());
// } catch (e) {
// logger('Failed to parse websocket message', e);
// return;
// }
// if (parsed.payload?.extensions?.authorization) {
// parsed.payload.extensions.authorization = {
// ...parsed.payload.extensions.authorization,
// ...authHeaders,
// };
// logger('WebSocket sending', JSON.stringify(parsed));
// return targetWs.send(JSON.stringify(parsed));
// }
// logger('WebSocket sending', data.toString());
// targetWs.send(data);
// });
// ws.on('close', () => {
// targetWs.close();
// });
// ws.on('error', (err) => {
// logger('WebSocket error from client: ', err);
// targetWs.close();
// });
//
// // Pass through messages from Amplify to the client
// targetWs.on('message', (data) => {
// logger('WebSocket received', data.toString());
// ws.send(data.toString());
// });
// targetWs.on('close', () => {
// ws.close();
// });
// targetWs.on('error', (err) => {
// logger('WebSocket error from Amplify: ', err);
// ws.close();
// });
// });
});
};

0 comments on commit 48e9ecc

Please sign in to comment.