rsocket / rsocket-js

JavaScript implementation of RSocket

Home Page:https://github.com/rsocket/rsocket-js

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

WebsocketServerTransport bind does not resolve when given a WebsocketServer which leverages an listening http.Server instance

viglucci opened this issue · comments

As described below, when calling bind on a WebsocketServerTransport created with a WebsocketServer that uses a listening http.Server, the bind call never resolves.

------- Original comment body:

Hi @viglucci, I'm finally getting around to integrating RSocket 1.0 in a greenfield project, so I'll be adding to this thread as and when I find anything worth sharing.

So far loving the simple integration with RxJS, particularly on the client side this has reduced our RSocket setup code by at least 10x. Great work on that.

I had one small hiccup that I've had to hack around on the server side. We're running an Express server with some "normal" HTTP endpoints, and we want RSocket to only listen on a /subscriptions URL. The way we're doing this is:

We have an existing httpServer: http.Server, and my initial instinct was to instantiate the transport like this:

  const websocketServer = new WebSocket.Server({
    server: httpServer,
    path: '/subscriptions',
  })
  const transport = new WebsocketServerTransport({
    wsCreator: () => websocketServer,
  })
  const rsocketServer = new RSocketServer({
    transport,
    // ...
  })

We were calling this as follows in our server setup code:

  await listen() // () => new Promise<void>((resolve) => httpServer.listen(env.port, resolve))
  await rsocketServer.bind()

This didn't work though, as rsocketServer.bind() never resolves.

I noticed that WebsocketServerTransport#connectServer uses the listening event to resolve the server:

websocketServer.addListener("listening", () => resolve(websocketServer));

Manually adding websocketServer.addListener('listening', () => console.log('I am listening')), and also adding 'connection' listeners showed me that the WebSocket server was listening correctly.

Instantiating the WebSocket.Server inside the wsCreator callback did not help either. WebSocket.Server just binds to the HTTP server's listening event (code), so this never emits if the server is already listening.

I can fix this for now by instantiating the RSocket server before listening on the HTTP server, eg.:

  const rsocketStarted = rsocketServer.bind()
  await listen()
  await rsocketStarted

...but it's a bit confusing that the order makes a difference.

I can see why we'd want to await the listening event inside connectServer, but is there potentially some way of checking whether the WebSocket.Server is already listening and immediately resolving if so?

Anyway not a blocker at all, just a papercut :)

Will report on more as I come across it & once again thanks a lot for working on this!

Originally posted by @lachenmayer in #158 (comment)