How to open multiple WebSockets

MiServer is Dyalog's APL-based web development framework

How to open multiple WebSockets

Postby PGilbert on Mon Jul 20, 2020 4:25 pm

What is the best way to open multiple WebSockets while using the HTMLRenderer in v18 ?

While you do in APL:
      InterceptedURLs←1 2⍴'ws://dyalog_root/' 1


and you do in JavaScript:
Code: Select all
ws1 = new WebSocket("ws://dyalog_root/");
ws2 = new WebSocket("ws://dyalog_root/");


what would be the way to differentiate that the WebSocketUpgradeEvent is coming from 'ws1' or 'ws2' ? I have tried adding something after the url (like: new WebSocket("ws://dyalog_root/ws1") but it does not show up in the url in APL).

Thanks in advance.
User avatar
PGilbert
 
Posts: 436
Joined: Sun Dec 13, 2009 8:46 pm
Location: Montréal, Québec, Canada

Re: How to open multiple WebSockets

Postby Brian|Dyalog on Wed Jul 22, 2020 5:46 am

Hi Pierre!

First, I was surprised to see that the URL that's specified in the call to new WebSocket() isn't reflected in the callback arguments in APL. I've reported this as a bug. That would have been the easiest, and in my opinion, the most obvious way to differentiate between WebSockets. However, I would recommend setting a wildcard in InterceptedURLs as in (1 2⍴'ws://dyalog_root/*' 1). Then, if the URL was properly sent, you could do:
Code: Select all
ws1 = new WebSocket("ws://dyalog_root/ws1")
ws2 = new WebSocket("ws://dyalog_root/ws2")

Until the actual URL is send as a part of the callback, I can think of a couple ways to differentiate between multiple WebSockets. The first is to send an identifying message immediately after opening the WebSocket. You have the WebSocket ID from the WebSocketUpgrade and WebSocketReceive events so you can keep track of as many WebSockets as you want.

The second method involves specifying a subprotocol when you create the WebSocket. In this instance, the subprotocol is nothing more than a differentiator for a WebSocket. There is a registry of subprotocols, so it's good practice to name your subprotocol something unique to your application. This is a bit more involved because the WebSocketUpgrade request needs to be manually validated. This is specified by setting a value of 2 in the second column of InterceptedURLs. In your JavaScript, you specify the subprotocol (do something like:
Code: Select all
ws1 = new WebSocket("ws://dyalog_root/","pierre.ws1")
ws2 = new WebSocket("ws://dyalog_root/","pierre.ws2")

In APL:
  • You need to set the second element of the InterceptedURLs entry to 2
    Code: Select all
         iURLs←('InterceptedURLs'(1 2⍴'ws://dyalog_root/*' 2))
  • In the WebSocketUpgrade event handler, inspect the Sec-WebSocket-Protocol to determine which WebSocket is being upgraded
    Code: Select all
         :Case 'WebSocketUpgrade'
             (obj ev wsid url hdr)←5↑args
             protocol←⊃'^Sec-WebSocket-Protocol: (.*)' ⎕S '\1'⊢hdr  ⍝ note ⎕ML←1 here
  • In the WebSocketUpgrade event handler result, you need to supply a Sec-WebSocket-Protocol header that matches the subprotocol in the request
    Code: Select all
             hdr←'Sec-WebSocket-Protocol: ',protocol,⎕UCS 13 10
             resp←obj ev wsid url hdr
I hope this helps!
/Brian
User avatar
Brian|Dyalog
 
Posts: 116
Joined: Thu Nov 26, 2009 4:02 pm
Location: West Henrietta, NY

Re: How to open multiple WebSockets

Postby PGilbert on Wed Jul 22, 2020 1:55 pm

Thanks Brian, this is answering perfectly my question.
User avatar
PGilbert
 
Posts: 436
Joined: Sun Dec 13, 2009 8:46 pm
Location: Montréal, Québec, Canada


Return to MiServer

Who is online

Users browsing this forum: No registered users and 1 guest