# WebSocket libraries for JSOO?

**URL:** <https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990>\
**Category:** Community\
**Created:** [February 2, 2024, 7:04am UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990 "2024-02-02T07:04:08Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Hans\_Ole\_Rafaelsen](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hans_ole_rafaelsen/32/5064_2.png) [@Hans\_Ole\_Rafaelsen](https://discuss.ocaml.org/u/Hans_Ole_Rafaelsen)\
**Post date:** [February 2, 2024, 7:04am UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/1 "2024-02-02T07:04:08Z")

</div>

Hi,

I’m trying to use WebSockets to communicate between an application using OCaml (Dream) on the server side and JSOO on the browser side. I have problems finding a library for this with JSOO.

- brr - looks promising, but it looks like it does not implement all required functions.

- vdom - seems to have WebSocket bindings.

Are there other libraries or solution for supporting WebSockets in JSOO?

At a more general level, I’m looking for a way for easy communication between the server and the browser, that also support push from the server. Something like [Meteor pubsub](https://docs.meteor.com/api/pubsub) or GraphQl. What is the best option for this in OCaml/JSOO?

Regards,

Hans Ole Rafaelsen

---

<div class="post-metadata">

**Author:** ![Simon\_ES](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/simon_es/32/4765_2.png) [@Simon\_ES](https://discuss.ocaml.org/u/Simon_ES)\
**Post date:** [February 2, 2024, 10:24am UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/2 "2024-02-02T10:24:21Z")

</div>

Eliom does all this automatically without having to think about it. You would save a lot of time

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [February 2, 2024, 10:31am UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/3 "2024-02-02T10:31:29Z")

</div>

> [@Hans\_Ole\_Rafaelsen](#):
>
> brr - looks promising, but it looks like it does not implement all required functions.

Which required functions are missing ?

---

<div class="post-metadata">

**Author:** ![Zoggy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/zoggy/32/2919_2.png) [@Zoggy](https://discuss.ocaml.org/u/Zoggy)\
**Post date:** [February 2, 2024, 10:32am UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/4 "2024-02-02T10:32:59Z")

</div>

[ocaml-websocket](https://github.com/vbmithr/ocaml-websocket) works.

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [February 2, 2024, 10:45am UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/5 "2024-02-02T10:45:23Z")

</div>

@zoggy that’s server side.

---

<div class="post-metadata">

**Author:** ![Zoggy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/zoggy/32/2919_2.png) [@Zoggy](https://discuss.ocaml.org/u/Zoggy)\
**Post date:** [February 2, 2024, 10:58am UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/6 "2024-02-02T10:58:41Z")

</div>

Sorry. I looked at some [old code](https://framagit.org/zoggy/ojs-base/-/blame/master/lib_js/ojs_js.ml?ref_type=heads#L53) which uses the [WebSockets](https://ocaml.org/p/js_of_ocaml/latest/doc/Js_of_ocaml/WebSockets/index.html) module in JSOO. This works well with OCaml-websocket on server side.

---

<div class="post-metadata">

**Author:** ![panglesd](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/panglesd/32/3931_2.png) [@panglesd](https://discuss.ocaml.org/u/panglesd)\
**Post date:** [February 2, 2024, 11:04am UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/7 "2024-02-02T11:04:58Z")

</div>

I’ve used `Brr` client-side for websocket and I did not miss any function!

However, I was bit by this issue: [Receiving websocket payloads larger than ~4K yields garbled data · Issue #214 · aantron/dream · GitHub](https://github.com/aantron/dream/issues/214)

Bascially, the client and server (dream) are discussing through websockets. When the server sends a long string, everything works well. When the client sends a long string, the string received by the server is garbage character at some point.  
So if your app might send lots of data in a single message, be aware of this!

---

<div class="post-metadata">

**Author:** ![Hans\_Ole\_Rafaelsen](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hans_ole_rafaelsen/32/5064_2.png) [@Hans\_Ole\_Rafaelsen](https://discuss.ocaml.org/u/Hans_Ole_Rafaelsen)\
**Post date:** [February 2, 2024, 12:02pm UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/8 "2024-02-02T12:02:22Z")

</div>

It’s probably me, not understanding how to use it properly. In JavaScript I would do something like:

```auto
    var socket = new WebSocket("ws://" + window.location.host + "/ws");

    socket.onopen = function () {
      socket.send("start");
    };

    socket.onmessage = function (e) {
        ...
    };

```

I’m able to connect to the server with `Brr_io.Websocket.create`, but I’m not able to use it. I was hoping to find similar functions as `onopen` and `onmessage`. At least the “addEventListener” method.

Is the “as\_target” function used for setting up handlers? Do you have examples on how to use this, or a full example that shows how to set up and use the socket?

---

<div class="post-metadata">

**Author:** ![Haudegen](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/haudegen/32/716_2.png) [@Haudegen](https://discuss.ocaml.org/u/Haudegen)\
**Post date:** [February 2, 2024, 4:23pm UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/9 "2024-02-02T16:23:15Z")

</div>

Js\_of\_ocaml [supports websockets](https://ocsigen.org/js_of_ocaml/latest/api/js_of_ocaml/Js_of_ocaml/WebSockets/index.html), you don’t need anything else.

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [February 2, 2024, 4:30pm UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/10 "2024-02-02T16:30:32Z")

</div>

> [@Hans\_Ole\_Rafaelsen](#):
>
> Is the “as\_target” function used for setting up handlers?

Sorry no sample code but yes you need to turn the websocket value into an event target and then use the [DOM event API](https://erratique.ch/software/brr/doc/Brr/Ev/index.html) to setup your handlers ([here’s](https://github.com/dbuenzli/brr/blob/06d3a6d0789a60329b89917c70a26f69ae1ad891/test/test_clipboard.ml#L32-L34) a random example which you can accomodate with the right events).

The websocket specific events are [here](https://erratique.ch/software/brr/doc/Brr_io/Websocket/Ev/index.html) a few generic ones are in the DOM Event API [here](https://erratique.ch/software/brr/doc/Brr/Ev/index.html#predefined_types) and the message event is [here](https://erratique.ch/software/brr/doc/Brr_io/Message/Ev/index.html).

The websocket API predates JavaScript promises so it’s a bit inconvenient to use.

---

<div class="post-metadata">

**Author:** ![Hans\_Ole\_Rafaelsen](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hans_ole_rafaelsen/32/5064_2.png) [@Hans\_Ole\_Rafaelsen](https://discuss.ocaml.org/u/Hans_Ole_Rafaelsen)\
**Post date:** [February 2, 2024, 6:47pm UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/11 "2024-02-02T18:47:53Z")

</div>

I have been using Eliom for some of my applications. I have 3 main issues with it that I don’t know how to solve.

Deployment is my biggest problem. I have tried solving it before.

[https://sympa.inria.fr/sympa/arc/ocsigen/2018-03/msg00005.html](https://sympa.inria.fr/sympa/arc/ocsigen/2018-03/msg00005.html)

[https://sympa.inria.fr/sympa/arc/ocsigen/2018-06/msg00000.html](https://sympa.inria.fr/sympa/arc/ocsigen/2018-06/msg00000.html)

My current solution is to copy the required subset of my development environment (opam installed packages) over to the target nodes, in addition to the application. That was one of my main motivations for trying out Dream. It creates a single binary that can be copied and run. It would be a lot of help if the demo in ocsigen-start also could be built as a single static binary.

The second issue was that I had some problem with the application consuming memory.

[https://sympa.inria.fr/sympa/arc/ocsigen/2018-02/msg00003.html](https://sympa.inria.fr/sympa/arc/ocsigen/2018-02/msg00003.html)

I’m not sure if it is a bug, or I’m not using it correctly. However, for my current usage, it is not a big issue.

The last issue is editor support. When working with these modules, getting type information and suggestions is a lot of help. I see there is some improvement lately, so it might be partly solved. I have not tested the latest setup.

---

<div class="post-metadata">

**Author:** ![Hans\_Ole\_Rafaelsen](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hans_ole_rafaelsen/32/5064_2.png) [@Hans\_Ole\_Rafaelsen](https://discuss.ocaml.org/u/Hans_Ole_Rafaelsen)\
**Post date:** [February 2, 2024, 6:49pm UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/12 "2024-02-02T18:49:55Z")

</div>

Thanks for the pointers. I’ll give it a try 😃

---

<div class="post-metadata">

**Author:** ![Hans\_Ole\_Rafaelsen](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hans_ole_rafaelsen/32/5064_2.png) [@Hans\_Ole\_Rafaelsen](https://discuss.ocaml.org/u/Hans_Ole_Rafaelsen)\
**Post date:** [February 2, 2024, 7:31pm UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/13 "2024-02-02T19:31:29Z")

</div>

I saw these definitions, but could not figure out how to use them. I thought they are interface definitions, and that they requires an implementation. Do you know where I might find examples on how to use them?

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [February 2, 2024, 8:03pm UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/14 "2024-02-02T20:03:27Z")

</div>

You can have a look at the code @zoggy mentioned. That being said I personally don’t find jsoo’s way of interacting with JavaScript very usable (more on this [here](https://erratique.ch/software/brr/doc/ffi_manual.html#foreword)).

---

<div class="post-metadata">

**Author:** ![Haudegen](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/haudegen/32/716_2.png) [@Haudegen](https://discuss.ocaml.org/u/Haudegen)\
**Post date:** [February 2, 2024, 9:27pm UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/15 "2024-02-02T21:27:50Z")

</div>

Maybe this helps to get started. Beware, that’s not production level code.

```auto
let rec connect_websocket token ws_url is_debug () = begin
  Log.info "Connecting WebSocket." ;
  Log.info (sprintf "Debugging: %b." is_debug) ;
  Log.info (sprintf "WS-URL: %s" ws_url) ;
  (* let host = Js.to_string (Dom_html.window##.location##.host) in *)
  let ws = new%js WebSockets.webSocket (Js.string ws_url) in
  let pp_intv_opt =
    if ws##.readyState = WebSockets.CONNECTING && is_debug then begin
      show_message (sprintf "Ping interval: %i ms." ping_interval_ms) ;
      Some (Jsoohelpers.Timers.set_interval ~timeout:ping_interval_ms
              (fun () -> ws##send (Js.string "PING") ; Log.debug "-> PING"))
    end
    else None
  in
  (* Window event listener: unload *)
  let ev_unl_id =
    Dom_html.addEventListener Dom_html.window Dom_html.Event.unload
      (Dom_html.handler (fun _ev ->
           (Log.warn "Window event: unload!" ; ws##close ; Js._true)))
    Js._true
  in
  (* WebSocket handler: onopen *)
  ws##.onopen := Dom.handler (fun _ev -> begin
        ws##send token ;
        Log.info "WebSocket connected." ;
        if is_debug then show_message "WebSocket connected." ;
        Js._true
      end) ;
  (* WebSocket handler: onclose *)
  ws##.onclose := Dom.handler (fun _ev -> begin
        Log.error "WebSocket connection closed!" ;
        (match pp_intv_opt with
         | Some intv -> begin
             Jsoohelpers.Timers.clear_interval intv ;
             Log.debug "Pingpong interval cleared."
           end
         | None -> ()) ;
        Dom_html.removeEventListener ev_unl_id ;
        ignore (Dom_html.setTimeout (connect_websocket token ws_url is_debug)
                  reconnect_timeout_ms) ;
        Js._true
      end) ;
  (* WebSocket handler: onerror *)
  ws##.onerror := Dom.handler (fun _ev -> begin
        Log.error "WebSocket error!" ;
        Js._true
      end) ;
  (* WebSocket handler: onmessage *)
  ws##.onmessage := Dom.handler (fun ev -> begin
        let msg = Js.to_string ev##.data in
        add_message msg ;
        (* if is_debug then show_message msg ; *)
        Js._true
      end)
end

```

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [February 2, 2024, 10:20pm UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/16 "2024-02-02T22:20:50Z")

</div>

> [@Hans\_Ole\_Rafaelsen](#):
>
> At a more general level, I’m looking for a way for easy communication between the server and the browser, that also support push from the server.

If you are not strongly tied to JSOO, maybe htmx with the WebSocket extension? [\</\> htmx ~ The websockets Extension](https://htmx.org/extensions/web-sockets/)

I have an [HTML generation library](https://github.com/yawaramin/dream-html) for Dream that supports htmx out of the box so you can write HTML directly in your Dream server code. Adapting the first snippet from the htmx page:

```auto
open Dream_html
open HTML

let chatroom = div [Hx.ext "ws"; Hx.ws_connect "/chatroom"] [
  div [id "notifications"] [];
  div [id "chat_room"] [
    ...
  ];
  form [id "form"; Hx.ws_send] [
    input [name "chat_message"];
  ];
]

```

So you render all the pages on the server side and htmx takes care of the network interactions on the client side ie setting up the WS, sending and receiving messages, reconnecting on disconnect. So in practice you have to write little or no JavaScript code.

---

<div class="post-metadata">

**Author:** ![Frederic\_Loyer](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/frederic_loyer/32/3472_2.png) [@Frederic\_Loyer](https://discuss.ocaml.org/u/Frederic_Loyer)\
**Post date:** [February 3, 2024, 6:02pm UTC](https://discuss.ocaml.org/t/websocket-libraries-for-jsoo/13990/17 "2024-02-03T18:02:45Z")

</div>

I have just seen [def/cuite: OCaml bindings to Qt toolkit. - cuite - Gitea: Git with a cup of tea](https://gitea.lakaban.net/def/cuite) a Qt5 binding, but not tested yet.

(It is based of C++ widgets, not the Qml language).
