(options: {
server: ServerType
fetchCallback: FetchCallback
wss: WebSocketServerLike
})
| 120 | } |
| 121 | |
| 122 | export const setupWebSocket = (options: { |
| 123 | server: ServerType |
| 124 | fetchCallback: FetchCallback |
| 125 | wss: WebSocketServerLike |
| 126 | }): void => { |
| 127 | const { server, fetchCallback, wss } = options |
| 128 | |
| 129 | const waiterMap = new Map< |
| 130 | IncomingMessage, |
| 131 | { resolve: (ws: WebSocketLike) => void; connectionSymbol: symbol } |
| 132 | >() |
| 133 | |
| 134 | wss.on('connection', (ws, request) => { |
| 135 | const waiter = waiterMap.get(request) |
| 136 | if (waiter) { |
| 137 | waiter.resolve(ws) |
| 138 | waiterMap.delete(request) |
| 139 | } |
| 140 | }) |
| 141 | |
| 142 | const waitForWebSocket: WaitForWebSocket = (request, connectionSymbol) => { |
| 143 | return new Promise<WebSocketLike>((resolve) => { |
| 144 | waiterMap.set(request, { resolve, connectionSymbol }) |
| 145 | }) |
| 146 | } |
| 147 | |
| 148 | server.on('upgrade', async (request, socket: Duplex, head) => { |
| 149 | if (request.headers.upgrade?.toLowerCase() !== 'websocket') { |
| 150 | return |
| 151 | } |
| 152 | |
| 153 | const env: UpgradeBindings = { |
| 154 | incoming: request, |
| 155 | outgoing: undefined, |
| 156 | wss, |
| 157 | [WAIT_FOR_WEBSOCKET_SYMBOL]: waitForWebSocket, |
| 158 | } |
| 159 | |
| 160 | let status = 400 |
| 161 | let responseHeaders: Headers | undefined |
| 162 | try { |
| 163 | const response = (await fetchCallback( |
| 164 | createUpgradeRequest(request), |
| 165 | env as unknown as Parameters<FetchCallback>[1] |
| 166 | )) as Response |
| 167 | if (response instanceof Response) { |
| 168 | status = response.status |
| 169 | responseHeaders = response.headers |
| 170 | } |
| 171 | } catch { |
| 172 | if (server.listenerCount('upgrade') === 1) { |
| 173 | rejectUpgradeRequest(socket, 500) |
| 174 | } |
| 175 | return |
| 176 | } |
| 177 | |
| 178 | const waiter = waiterMap.get(request) |
| 179 |
no test coverage detected
searching dependent graphs…