Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | 2x 11x 23x 21x 21x 1x 20x 20x 18x 18x 9x 9x 9x 6x 3x | /**
* Pure helpers for the socket.io v0.9 handshake exchange.
*
* The legacy handshake is a single HTTP GET to `/socket.io/1/` (with an
* optional JSONP `?t=` or `?jsonp=` query that we ignore). The response
* body is a colon-delimited tuple:
*
* `<sid>:<hbTimeoutSec>:<closeTimeoutSec>:<transports>`
*
* Example: `abcd1234:60:60:websocket,xhr-polling`
*
* After that the client picks a transport and upgrades/polls at
* `/socket.io/1/<transport>/<sid>`. We route each transport separately.
*
* Path forms we accept:
* - `/socket.io/1/` handshake
* - `/socket.io/1/websocket/<sid>` WS upgrade
* - `/socket.io/1/xhr-polling/<sid>` long-poll
* - `/socket.io/1/jsonp-polling/<sid>/<i>` jsonp long-poll (rarely used)
*
* An optional `BASEPATH` prefix is allowed: any leading path up to the
* literal `/socket.io/` is stripped before matching. This mirrors the
* `BASEPATH` env-var pattern the worker already uses for other routes
* (§7 item 32 — CLI ports that knob through).
*/
/** Default transports list matches the legacy server's advertised set. */
export const DEFAULT_TRANSPORTS = ['websocket', 'xhr-polling'] as const;
export interface HandshakeOptions {
/** Session id generated per handshake; opaque to the client. */
sid: string;
/** Heartbeat timeout in seconds. Server sends `2::` every hbTimeoutSec/2. */
hbTimeoutSec: number;
/** Close timeout — how long the client waits before reconnecting. */
closeTimeoutSec: number;
/** Transports advertised to the client (order = preference). */
transports: readonly string[];
}
/**
* Build the handshake response body. No headers — Content-Type is
* `text/plain; charset=utf-8` and is set by the worker at the call site.
*/
export function buildHandshakeResponse(opts: HandshakeOptions): string {
return `${opts.sid}:${opts.hbTimeoutSec}:${opts.closeTimeoutSec}:${opts.transports.join(',')}`;
}
export interface HandshakePathMatch {
/** "handshake" for `/socket.io/1/`; otherwise the transport name. */
transport?: string;
/** Present for transport routes; undefined for the initial handshake. */
sid?: string;
}
/**
* Regex-parse a URL's pathname against the legacy socket.io path family.
*
* Accepts any fully-qualified URL or raw pathname. Returns `null` when
* the path doesn't match any legacy form — callers should treat that as
* "not socket.io territory, fall through".
*
* Returns:
* - `{}` for `/socket.io/1/` (the initial handshake)
* - `{ transport, sid }` for transport routes
*
* We don't return the jsonp-polling `i` suffix separately; it isn't used
* by any current sheetnode-era client we support. If it ever matters the
* adapter can pull it from the raw URL.
*/
export function parseHandshakePath(url: string): HandshakePathMatch | null {
if (typeof url !== 'string' || url.length === 0) return null;
// Strip query/fragment and accept both full URLs and bare paths.
let pathname: string;
try {
// Use a synthetic base so relative paths work with the URL ctor.
pathname = new URL(url, 'http://x').pathname;
} catch {
return null;
}
// Strip any BASEPATH prefix — everything before `/socket.io/`.
const anchor = pathname.indexOf('/socket.io/');
if (anchor === -1) return null;
const tail = pathname.slice(anchor);
// Initial handshake: `/socket.io/1/` (trailing slash required by spec;
// also accept without it for liberal clients).
if (tail === '/socket.io/1/' || tail === '/socket.io/1') {
return {};
}
// Transport routes: `/socket.io/1/<transport>/<sid>[/<i>]`
// Transport = lowercase letters + hyphen; sid = URL-safe token.
const m = /^\/socket\.io\/1\/([a-z-]+)\/([A-Za-z0-9_-]+)(?:\/[^/]*)?\/?$/.exec(tail);
if (m) {
return { transport: m[1]!, sid: m[2]! };
}
return null;
}
|