Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(client): Add Query Parameter Support to WebSocket Client in hono/client #3066

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions src/client/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1044,6 +1044,80 @@ describe('WebSocket URL Protocol Translation', () => {
})
})

describe('WebSocket URL Protocol Translation with Query Parameters', () => {
const app = new Hono()
const route = app.get(
'/',
upgradeWebSocket((c) => ({
onMessage(event, ws) {
ws.send('Hello from server!')
},
onClose: () => {
console.log('Connection closed')
},
}))
)

type AppType = typeof route

const server = setupServer()
const webSocketMock = vi.fn()

beforeAll(() => server.listen())
beforeEach(() => {
vi.stubGlobal('WebSocket', webSocketMock)
})
afterEach(() => {
vi.clearAllMocks()
server.resetHandlers()
})
afterAll(() => server.close())

it('Translates HTTP to ws and includes query parameters', async () => {
const client = hc<AppType>('http://localhost')
client.index.$ws({
query: {
id: '123',
type: 'test',
},
})
expect(webSocketMock).toHaveBeenCalledWith('ws://localhost/index?id=123&type=test')
})

it('Translates HTTPS to wss and includes query parameters', async () => {
const client = hc<AppType>('https://localhost')
client.index.$ws({
query: {
id: '456',
type: 'secure',
},
})
expect(webSocketMock).toHaveBeenCalledWith('wss://localhost/index?id=456&type=secure')
})

it('Keeps ws unchanged and includes query parameters', async () => {
const client = hc<AppType>('ws://localhost')
client.index.$ws({
query: {
id: '789',
type: 'plain',
},
})
expect(webSocketMock).toHaveBeenCalledWith('ws://localhost/index?id=789&type=plain')
})

it('Keeps wss unchanged and includes query parameters', async () => {
const client = hc<AppType>('wss://localhost')
client.index.$ws({
query: {
id: '1011',
type: 'secure',
},
})
expect(webSocketMock).toHaveBeenCalledWith('wss://localhost/index?id=1011&type=secure')
})
})

describe('Client can be console.log in react native', () => {
it('Returns a function name with function.name.toString', async () => {
const client = hc('http://localhost')
Expand Down
8 changes: 6 additions & 2 deletions src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,16 @@ export const hc = <T extends Hono<any, any, any>>(
return new URL(url)
}
if (method === 'ws') {
const targetUrl = replaceUrlProtocol(
const webSocketUrl = replaceUrlProtocol(
opts.args[0] && opts.args[0].param ? replaceUrlParam(url, opts.args[0].param) : url,
'ws'
)
const targetUrl = new URL(webSocketUrl)
for (const key in opts.args[0]?.query) {
targetUrl.searchParams.set(key, opts.args[0].query[key])
}

return new WebSocket(targetUrl)
return new WebSocket(targetUrl.toString())
}

const req = new ClientRequestImpl(url, method)
Expand Down