question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

When trying to use websockets the connection hangs on trying to connect

See original GitHub issue

I was attempting to use WebSockets and whenever using itty-durable the connection hangs on trying to connect. Below is a small little code sample of what I am using to test the WebSockets. When I use it outside the scope of itty-durable (just on a normal route) it works fine.

import { ThrowableRouter } from 'itty-router-extras'
import { createIttyDurable, withDurables } from 'itty-durable'

export class TestWebsocket extends createIttyDurable({ persistOnChange: false }) {
	constructor(state, env) {
		super(state, env)
	}

	websocket() {
		const [client, websocket] = Object.values(new WebSocketPair())

		websocket.accept()

		websocket.send(JSON.stringify({ connected: true }))

		websocket.addEventListener('message', ({ data }) => {
			websocket.send(JSON.stringify({ data }))
		})

		return new Response(null, { status: 101, webSocket: client })
	}
}

const router = ThrowableRouter()

router.all('*', withDurables())

// Doesnt work
router.get('/ws', ({ TestWebsocket }) => TestWebsocket.get('test').websocket())

// Works
router.get('/ws2', () => {
	const [client, websocket] = Object.values(new WebSocketPair())

	websocket.accept()

	websocket.send(JSON.stringify({ connected: true }))

	websocket.addEventListener('message', ({ data }) => {
		websocket.send(JSON.stringify({ data }))
	})

	return new Response(null, { status: 101, webSocket: client })
})

export default {
	fetch: router.handle
}

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:10 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
AndrewLestercommented, Dec 27, 2022

Would also like to contribute to make this happen, and before doing any work I’d like to summarize what (I think?) the challenges might be:

  • As mentioned above, the Upgrade: websocket header needs to be sent to the DO when making a proxy’d function fetch. In doing this, maybe it makes sense to forward all headers of the current request over to the DO? This is assuming users of itty-durable will write something like DurableObject.connect({ connectionData }), where connect is a user defined DO method that returns a Response with a webSocket property.
  • The proxy’d function fetch that you’d get from writing DurableObject.connect({ connectionData }), currently, is only ever a POST request. But, from what I can tell, WebSocket connections MUST be initiated with a GET request. It’s weird because on Miniflare (--local) a POST request works just fine, so long as I’ve got the header. On “non-local” dev mode with wrangler, using a POST request with this setup just crashes wrangler completely. This line in kj might have to do with it? Not sure, maybe I’m just not doing it right. Either way, it seems like it’d be good to use a GET request since that’s standard practice.

Going about implementing all this, forwarding all request headers through with the proxy’d function fetch request doesn’t seem too difficult IF that’s a sensible solution. Maybe forwarding all headers is a bad idea? I’m not sure.

With the POST vs GET issue, it seems like the proxy’d function fetches with POST are pretty ingrained in the system, so breaking out of that for WebSockets could be less pretty. Perhaps the proxyDurable function’s get handler could detect the Upgrade: websocket header, and thus perform a GET request instead of a POST? This wouldn’t support a request body though, which could instead be turned into URL params and be picked up by the itty-durable DO internal router.

1reaction
tyvdhcommented, Jun 16, 2022

Dug into this a bit and it would appear that there’s a header issue or maybe just a response issue where the webSocket: client isn’t being forwarded when responding. This is either before the pass back or actually in the pass in where the headers.Upgrade: 'websocket' isn’t being passed to the method call into the DO.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Using new Websocket(<uri>) causes the websocket to hang ...
The client cycles through the connections to make and tries each one in order. If it fails or succeeds, it goes to the...
Read more >
Websockets are stuck in CONNECTING state. #2098 - GitHub
I'm trying to connect to a local websocket server. socket = new WebSocket("ws://localhost:30003"); The socket never connects properly.
Read more >
Troubleshooting connection issues | Socket.IO
You are trying to reach a plain WebSocket server; The server is not reachable; The client is not compatible with the version of...
Read more >
IT23126: WEBSOCKETS CLIENT CAN HANG WAITING FOR ...
When upgrading and using a WebSockets connection through DataPower to a back-end server, the client can sometimes hang.
Read more >
Websockets service crashes after unexpected closing ... - MSDN
Websockets service crashes (only websockets) if client disconnects without normal closing connection (just close application).
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found