summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hero.mjs99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/hero.mjs b/src/hero.mjs
index 859d86f..6df57ea 100644
--- a/src/hero.mjs
+++ b/src/hero.mjs
@@ -38,6 +38,105 @@ export const makeLogger = (writerFn = console.error) => ({
export const log = makeLogger();
+export const isValidMethod = method =>
+ method === "GET";
+
+export const isValidUpgrade = val =>
+ val.toLowerCase() === "websocket";
+
+export const isValidKey = key =>
+ /^[0-9a-zA-Z+/]{22}==$/.test(key);
+
+export const isValidVersion = n =>
+ n === 13;
+
+export const validateUpgrade = (method, headers) => {
+ const upgrade = headers["upgrade"];
+ const key = headers["sec-websocket-key"];
+ const versionStr = headers["sec-websocket-version"];
+ const version = parseInt(versionStr);
+
+ if (!isValidMethod(method)) {
+ return {
+ isValid: false,
+ response: {
+ status: 405,
+ },
+ };
+ }
+
+ if (!upgrade) {
+ return {
+ isValid: false,
+ response: {
+ status: 400,
+ body: 'Missing "Upgrade" header\n',
+ },
+ };
+ }
+
+ if (!isValidUpgrade(upgrade)) {
+ return {
+ isValid: false,
+ response: {
+ status: 400,
+ body: 'Invalid "Upgrade" value\n',
+ },
+ };
+ }
+
+ if (!key) {
+ return {
+ isValid: false,
+ response: {
+ status: 400,
+ body: 'Missing "Sec-WebSocket-Key" header\n',
+ },
+ };
+ }
+
+ if (!isValidKey(key)) {
+ return {
+ isValid: false,
+ response: {
+ status: 400,
+ body: 'Invalid "Sec-WebSocket-Key" value\n',
+ },
+ };
+ }
+
+ if (!version) {
+ return {
+ isValid: false,
+ response: {
+ status: 400,
+ body: 'Missing "Sec-WebSocket-Version" header\n',
+ },
+ };
+ }
+
+ if (!isValidVersion(version)) {
+ return {
+ isValid: false,
+ response: {
+ status: 400,
+ body: 'Invalid "Sec-WebSocket-Version" value\n',
+ },
+ };
+ }
+
+ return {
+ isValid: true,
+ };
+};
+
+const GUID_MAGIC_NUMBER = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+export const computeHash = key =>
+ crypto
+ .createHash("SHA1")
+ .update(key + GUID_MAGIC_NUMBER)
+ .digest("base64");
+
export const interceptorsFn = ({
uuidFn = crypto.randomUUID,
logger = log,