Compare commits

..

1 Commits

Author SHA1 Message Date
ms ec5f40760e
Merge f962d29eda into 0dc8b719b4 2025-04-28 19:22:49 +03:00
4 changed files with 14 additions and 69 deletions

View File

@ -1,11 +1,5 @@
# @hono/node-ws # @hono/node-ws
## 1.1.4
### Patch Changes
- [#1146](https://github.com/honojs/middleware/pull/1146) [`b8453438b66fc9a6af58e33593e9fa21a96c02a7`](https://github.com/honojs/middleware/commit/b8453438b66fc9a6af58e33593e9fa21a96c02a7) Thanks [@nakasyou](https://github.com/nakasyou)! - enhance WebSocket connection handling with CORS support and connection symbols
## 1.1.3 ## 1.1.3
### Patch Changes ### Patch Changes

View File

@ -1,6 +1,6 @@
{ {
"name": "@hono/node-ws", "name": "@hono/node-ws",
"version": "1.1.4", "version": "1.1.3",
"description": "WebSocket helper for Node.js", "description": "WebSocket helper for Node.js",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",

View File

@ -3,7 +3,6 @@ import { serve } from '@hono/node-server'
// @ts-ignore // @ts-ignore
import type { ServerType } from '@hono/node-server/dist/types' import type { ServerType } from '@hono/node-server/dist/types'
import { Hono } from 'hono' import { Hono } from 'hono'
import { cors } from 'hono/cors'
import type { WSMessageReceive } from 'hono/ws' import type { WSMessageReceive } from 'hono/ws'
import { WebSocket } from 'ws' import { WebSocket } from 'ws'
import { createNodeWebSocket } from '.' import { createNodeWebSocket } from '.'
@ -245,42 +244,4 @@ describe('WebSocket helper', () => {
createNodeWebSocket({ app }) createNodeWebSocket({ app })
}) })
}) })
it('Should client can connect when use cors()', async () => {
app.use(cors())
const mainPromise = new Promise<boolean>((resolve) =>
app.get(
'/',
upgradeWebSocket(() => ({
onOpen() {
resolve(true)
},
}))
)
)
new WebSocket('ws://localhost:3030/')
expect(await mainPromise).toBe(true)
})
it('Should client can connect even if a response has difference', async () => {
app.use(async (c, next) => {
c.res = new Response(null, c.res)
await next()
})
const mainPromise = new Promise<boolean>((resolve) =>
app.get(
'/',
upgradeWebSocket(() => ({
onOpen() {
resolve(true)
},
}))
)
)
new WebSocket('ws://localhost:3030/')
expect(await mainPromise).toBe(true)
})
}) })

View File

@ -23,11 +23,6 @@ export interface NodeWebSocketInit {
baseUrl?: string | URL baseUrl?: string | URL
} }
const generateConnectionSymbol = () => Symbol('connection')
/** @example `c.env[CONNECTION_SYMBOL_KEY]` */
const CONNECTION_SYMBOL_KEY: unique symbol = Symbol('CONNECTION_SYMBOL_KEY')
/** /**
* Create WebSockets for Node.js * Create WebSockets for Node.js
* @param init Options * @param init Options
@ -37,7 +32,7 @@ export const createNodeWebSocket = (init: NodeWebSocketInit): NodeWebSocket => {
const wss = new WebSocketServer({ noServer: true }) const wss = new WebSocketServer({ noServer: true })
const waiterMap = new Map< const waiterMap = new Map<
IncomingMessage, IncomingMessage,
{ resolve: (ws: WebSocket) => void; connectionSymbol: symbol } { resolve: (ws: WebSocket) => void; response: Response }
>() >()
wss.on('connection', (ws, request) => { wss.on('connection', (ws, request) => {
@ -48,9 +43,9 @@ export const createNodeWebSocket = (init: NodeWebSocketInit): NodeWebSocket => {
} }
}) })
const nodeUpgradeWebSocket = (request: IncomingMessage, connectionSymbol: symbol) => { const nodeUpgradeWebSocket = (request: IncomingMessage, response: Response) => {
return new Promise<WebSocket>((resolve) => { return new Promise<WebSocket>((resolve) => {
waiterMap.set(request, { resolve, connectionSymbol }) waiterMap.set(request, { resolve, response })
}) })
} }
@ -67,18 +62,14 @@ export const createNodeWebSocket = (init: NodeWebSocketInit): NodeWebSocket => {
headers.append(key, Array.isArray(value) ? value[0] : value) headers.append(key, Array.isArray(value) ? value[0] : value)
} }
const env: { const response = await init.app.request(
incoming: IncomingMessage url,
outgoing: undefined { headers: headers },
[CONNECTION_SYMBOL_KEY]?: symbol { incoming: request, outgoing: undefined }
} = { )
incoming: request,
outgoing: undefined,
}
await init.app.request(url, { headers: headers }, env)
const waiter = waiterMap.get(request)
if (!waiter || waiter.connectionSymbol !== env[CONNECTION_SYMBOL_KEY]) { const waiter = waiterMap.get(request)
if (!waiter || waiter.response !== response) {
socket.end( socket.end(
'HTTP/1.1 400 Bad Request\r\n' + 'HTTP/1.1 400 Bad Request\r\n' +
'Connection: close\r\n' + 'Connection: close\r\n' +
@ -102,10 +93,9 @@ export const createNodeWebSocket = (init: NodeWebSocketInit): NodeWebSocket => {
return return
} }
const connectionSymbol = generateConnectionSymbol() const response = new Response()
c.env[CONNECTION_SYMBOL_KEY] = connectionSymbol
;(async () => { ;(async () => {
const ws = await nodeUpgradeWebSocket(c.env.incoming, connectionSymbol) const ws = await nodeUpgradeWebSocket(c.env.incoming, response)
let events: WSEvents<WebSocket> let events: WSEvents<WebSocket>
try { try {
events = await createEvents(c) events = await createEvents(c)
@ -177,7 +167,7 @@ export const createNodeWebSocket = (init: NodeWebSocketInit): NodeWebSocket => {
}) })
})() })()
return new Response() return response
}, },
} }
} }