Skip to content

Commit 519404a

Browse files
authored
fix(node-ws): adapter shouldn't send buffer as a event (#1094)
* fix(node-ws): adapter shouldn't send buffer as a event * chore: changeset
1 parent b18f243 commit 519404a

File tree

9 files changed

+56
-48
lines changed

9 files changed

+56
-48
lines changed

Diff for: .changeset/giant-papayas-taste.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@hono/node-ws': patch
3+
---
4+
5+
Adapter won't send Buffer as a MessageEvent.

Diff for: packages/cloudflare-access/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Context } from 'hono'
2-
import { getCookie } from 'hono/cookie';
2+
import { getCookie } from 'hono/cookie'
33
import { createMiddleware } from 'hono/factory'
44
import { HTTPException } from 'hono/http-exception'
55

Diff for: packages/node-ws/src/index.test.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,7 @@ describe('WebSocket helper', () => {
5252
})
5353

5454
it('Should be rejected if upgradeWebSocket is not used', async () => {
55-
app.get(
56-
'/', (c)=>c.body('')
57-
)
55+
app.get('/', (c) => c.body(''))
5856

5957
{
6058
const ws = new WebSocket('ws://localhost:3030/')
@@ -70,7 +68,8 @@ describe('WebSocket helper', () => {
7068
expect(await mainPromise).toBe(true)
7169
}
7270

73-
{ //also should rejected on fallback
71+
{
72+
//also should rejected on fallback
7473
const ws = new WebSocket('ws://localhost:3030/notFound')
7574
const mainPromise = new Promise<boolean>((resolve) => {
7675
ws.onerror = () => {
@@ -202,11 +201,11 @@ describe('WebSocket helper', () => {
202201
ws.send(binaryData)
203202

204203
const receivedMessage = await mainPromise
205-
expect(receivedMessage).toBeInstanceOf(Buffer)
206-
expect((receivedMessage as Buffer).byteLength).toBe(binaryData.length)
204+
expect(receivedMessage).toBeInstanceOf(ArrayBuffer)
205+
expect((receivedMessage as ArrayBuffer).byteLength).toBe(binaryData.length)
207206

208207
binaryData.forEach((val, idx) => {
209-
expect((receivedMessage as Buffer).at(idx)).toBe(val)
208+
expect(new Uint8Array(receivedMessage as ArrayBuffer)[idx]).toBe(val)
210209
})
211210
})
212211

Diff for: packages/node-ws/src/index.ts

+12-5
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ export interface NodeWebSocketInit {
2525
*/
2626
export const createNodeWebSocket = (init: NodeWebSocketInit): NodeWebSocket => {
2727
const wss = new WebSocketServer({ noServer: true })
28-
const waiterMap = new Map<IncomingMessage, { resolve: (ws: WebSocket) => void, response: Response }>()
28+
const waiterMap = new Map<
29+
IncomingMessage,
30+
{ resolve: (ws: WebSocket) => void; response: Response }
31+
>()
2932

3033
wss.on('connection', (ws, request) => {
3134
const waiter = waiterMap.get(request)
@@ -64,9 +67,9 @@ export const createNodeWebSocket = (init: NodeWebSocketInit): NodeWebSocket => {
6467
if (!waiter || waiter.response !== response) {
6568
socket.end(
6669
'HTTP/1.1 400 Bad Request\r\n' +
67-
'Connection: close\r\n' +
68-
'Content-Length: 0\r\n' +
69-
'\r\n'
70+
'Connection: close\r\n' +
71+
'Content-Length: 0\r\n' +
72+
'\r\n'
7073
)
7174
waiterMap.delete(request)
7275
return
@@ -113,7 +116,11 @@ export const createNodeWebSocket = (init: NodeWebSocketInit): NodeWebSocket => {
113116
for (const data of datas) {
114117
events.onMessage?.(
115118
new MessageEvent('message', {
116-
data: isBinary ? data : data.toString('utf-8'),
119+
data: isBinary
120+
? data instanceof ArrayBuffer
121+
? data
122+
: data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength)
123+
: data.toString('utf-8'),
117124
}),
118125
ctx
119126
)

Diff for: packages/oauth-providers/src/providers/twitch/authFlow.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,13 @@ export class AuthFlow {
7777

7878
const url = 'https://id.twitch.tv/oauth2/token'
7979

80-
const response = (await fetch(url, {
80+
const response = await fetch(url, {
8181
method: 'POST',
8282
headers: {
8383
'Content-Type': 'application/x-www-form-urlencoded',
8484
},
8585
body: parsedOptions,
86-
}).then((res) => res.json() as Promise<TwitchTokenResponse>))
86+
}).then((res) => res.json() as Promise<TwitchTokenResponse>)
8787

8888
if ('error' in response) {
8989
throw new HTTPException(400, { message: response.error })

Diff for: packages/oauth-providers/src/providers/twitch/refreshToken.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@ export async function refreshToken(
1414
client_secret,
1515
})
1616

17-
const response = (await fetch('https://id.twitch.tv/oauth2/token', {
17+
const response = await fetch('https://id.twitch.tv/oauth2/token', {
1818
method: 'POST',
1919
headers: {
2020
'Content-Type': 'application/x-www-form-urlencoded',
2121
},
2222
body: params,
23-
}).then((res) => res.json() as Promise<TwitchRefreshResponse>))
23+
}).then((res) => res.json() as Promise<TwitchRefreshResponse>)
2424

2525
if ('error' in response) {
2626
throw new HTTPException(400, { message: response.error })
2727
}
28-
28+
2929
if ('message' in response) {
3030
throw new HTTPException(400, { message: response.message as string })
3131
}

Diff for: packages/oauth-providers/src/providers/twitch/revokeToken.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ import { HTTPException } from 'hono/http-exception'
22
import { toQueryParams } from '../../utils/objectToQuery'
33
import type { TwitchRevokingResponse } from './types'
44

5-
export async function revokeToken(
6-
client_id: string,
7-
token: string
8-
): Promise<boolean> {
5+
export async function revokeToken(client_id: string, token: string): Promise<boolean> {
96
const params = toQueryParams({
107
client_id: client_id,
118
token,
@@ -23,14 +20,16 @@ export async function revokeToken(
2320
if (!res.ok) {
2421
// Try to parse error response
2522
try {
26-
const errorResponse = await res.json() as TwitchRevokingResponse
23+
const errorResponse = (await res.json()) as TwitchRevokingResponse
2724
if (errorResponse && typeof errorResponse === 'object' && 'message' in errorResponse) {
2825
throw new HTTPException(400, { message: errorResponse.message })
2926
}
30-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
27+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
3128
} catch (e) {
3229
// If parsing fails, throw a generic error with the status
33-
throw new HTTPException(400, { message: `Token revocation failed with status: ${res.status}` })
30+
throw new HTTPException(400, {
31+
message: `Token revocation failed with status: ${res.status}`,
32+
})
3433
}
3534
}
3635

Diff for: packages/oauth-providers/src/providers/twitch/types.ts

+19-18
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ export type Scopes =
22
// Analytics
33
| 'analytics:read:extensions'
44
| 'analytics:read:games'
5-
5+
66
// Bits
77
| 'bits:read'
8-
8+
99
// Channel
1010
| 'channel:bot'
1111
| 'channel:manage:ads'
@@ -85,11 +85,11 @@ export type Scopes =
8585
| 'moderator:read:vips'
8686
| 'moderator:read:warnings'
8787
| 'moderator:manage:warnings'
88-
88+
8989
// IRC Chat Scopes
9090
| 'chat:edit'
9191
| 'chat:read'
92-
92+
9393
// PubSub-specific Chat Scopes
9494
| 'whispers:read'
9595

@@ -110,7 +110,6 @@ export type TwitchRefreshError = Required<Pick<TwitchErrorResponse, 'status' | '
110110

111111
export type TwitchTokenError = Required<Pick<TwitchErrorResponse, 'status' | 'message' | 'error'>>
112112

113-
114113
// Success responses types from Twitch API
115114
export interface TwitchValidateSuccess {
116115
client_id: string
@@ -150,19 +149,21 @@ export type TwitchTokenResponse = TwitchTokenSuccess | TwitchTokenError
150149
export type TwitchValidateResponse = TwitchValidateSuccess | TwitchValidateError
151150

152151
export interface TwitchUserResponse {
153-
data: [{
154-
id: string
155-
login: string
156-
display_name: string
157-
type: string
158-
broadcaster_type: string
159-
description: string
160-
profile_image_url: string
161-
offline_image_url: string
162-
view_count: number
163-
email: string
164-
created_at: string
165-
}]
152+
data: [
153+
{
154+
id: string
155+
login: string
156+
display_name: string
157+
type: string
158+
broadcaster_type: string
159+
description: string
160+
profile_image_url: string
161+
offline_image_url: string
162+
view_count: number
163+
email: string
164+
created_at: string
165+
}
166+
]
166167
}
167168

168169
export type TwitchUser = TwitchUserResponse['data'][0]

Diff for: packages/oauth-providers/src/providers/twitch/validateToken.ts

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import { HTTPException } from 'hono/http-exception'
22
import type { TwitchValidateResponse } from './types'
33

4-
export async function validateToken(
5-
token: string
6-
): Promise<TwitchValidateResponse> {
7-
4+
export async function validateToken(token: string): Promise<TwitchValidateResponse> {
85
const response = await fetch('https://id.twitch.tv/oauth2/validate', {
96
method: 'GET',
107
headers: {
11-
authorization: `Bearer ${token}`,
8+
authorization: `Bearer ${token}`,
129
},
1310
}).then((res) => res.json() as Promise<TwitchValidateResponse>)
1411

0 commit comments

Comments
 (0)