Last active
February 8, 2021 14:50
-
-
Save mwilliamson/969b9f6ee1bc5384ad38dd802a53beef to your computer and use it in GitHub Desktop.
WebSocket server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function handleConnect(url: string) { | |
setState({type: "connecting"}); | |
const socket = new WebSocket(url); | |
let nextMessageIndex = 0; | |
socket.onmessage = function (event) { | |
const message = JSON.parse(event.data); | |
if (message.index !== nextMessageIndex) { | |
setState({type: "sync-error"}); | |
socket.close(); | |
} | |
nextMessageIndex++; | |
const update = JSON.parse(message.payload) as StateUpdate; | |
setState(state => { | |
if (state.type === "connected") { | |
return {...state, state: updateState(state.state, update)}; | |
} else { | |
return state; | |
} | |
}); | |
}; | |
socket.onerror = function() { | |
setState({type: "connection-error"}); | |
}; | |
socket.onopen = function() { | |
setState({ | |
type: "connected", | |
state: initialState(), | |
socket: socket, | |
}); | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const http = require("http"); | |
const url = require("url"); | |
const serveHandler = require("serve-handler"); | |
const uuid = require("uuid"); | |
const WebSocket = require("ws"); | |
const webSocketPath = "/" + (process.argv[2] || uuid.v4()); | |
const port = process.env.PORT || 8000; | |
const server = http.createServer(function (request, response) { | |
if (/^\/static/.test(url.parse(request.url).pathname)) { | |
serveHandler(request, response, { | |
cleanUrls: false, | |
public: "static/build", | |
rewrites: [ | |
{ | |
"source": "/x", | |
"destination": "index.html" | |
}, | |
{ | |
"source": "/x/:a", | |
"destination": "/:a" | |
}, | |
{ | |
"source": "/x/:a/:b", | |
"destination": "/:a/:b" | |
}, | |
{ | |
"source": "/x/:a/:b/:c", | |
"destination": "/:a/:b/:c" | |
}, | |
{ | |
"source": "/x/:a/:b/:c/:d", | |
"destination": "/:a/:b/:c/:d" | |
}, | |
], | |
}); | |
} else { | |
response.writeHead(404, {"Content-Type": "text/plain"}); | |
response.end("404 Not Found"); | |
} | |
}); | |
console.log(`Server URI: ws://0.0.0.0:${port}${webSocketPath}`); | |
const wss = new WebSocket.Server({noServer: true}); | |
let connections = []; | |
const messages = []; | |
wss.on("connection", function connection(ws) { | |
connections.push(ws); | |
const intervalId = setInterval(() => { | |
ws.ping(); | |
}, 1000); | |
messages.forEach(message => ws.send(message)); | |
ws.on("close", () => { | |
connections = connections.filter(connection => connection != ws); | |
clearInterval(intervalId); | |
}); | |
ws.on("message", function incoming(payload) { | |
const message = JSON.stringify({ | |
index: messages.length, | |
payload: payload, | |
}); | |
messages.push(message); | |
connections.forEach((ws) => ws.send(message)); | |
}); | |
}); | |
server.on("upgrade", function upgrade(request, socket, head) { | |
const requestPath = url.parse(request.url).pathname; | |
if (requestPath === webSocketPath) { | |
wss.handleUpgrade(request, socket, head, function done(ws) { | |
wss.emit("connection", ws, request); | |
}); | |
} else { | |
socket.destroy(); | |
} | |
}); | |
server.listen(port); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment