| 24 | } |
| 25 | if (ServerError.is(err)) { |
| 26 | return res.status(err.status).json({ message: err.message }) |
| 27 | } else { |
| 28 | return res.status(500).json({ message: 'Internal Server Error' }) |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | /** |
| 33 | * Releases the raw socket behind an upgrade request that no route took |
| 34 | * ownership of, and reports whether it did. Returns false for ordinary |
| 35 | * requests, which still want a normal response. |
| 36 | * |
| 37 | * Both error paths need this. Express skips plain middleware once an error is |
| 38 | * in flight, so the cleanup middleware at the end of the stack is unreachable |
| 39 | * from either of them, and an upgrade's `res` is a detached dummy that swallows |
| 40 | * whatever is written to it — leaving the client hanging until it times out. |
| 41 | */ |
| 42 | export const ownsUnhandledUpgrade = (req: Request): boolean => |
| 43 | req.ws !== undefined && req.ws.handled === false |
| 44 | |
| 45 | const releaseUnhandledUpgrade = (req: Request): boolean => { |
| 46 | if (!ownsUnhandledUpgrade(req)) return false |
| 47 | req.ws?.socket.destroy() |
| 48 | return true |
nothing calls this directly
no outgoing calls
no test coverage detected