rstudio / httpuv

HTTP and WebSocket server package for R
Other
224 stars 84 forks source link

Send WS ping frames every 20 seconds #359

Closed jcheng5 closed 1 year ago

jcheng5 commented 1 year ago

Manual testing performed

I used this build of httpuv with Shiny, both locally and deployed over Hugging Face Spaces, using Wireshark to make sure that Ping packets were being sent at the correct intervals.

I also used this torture test app:

library(httpuv)

big_string <- strrep("j", 1e6)

app <- list(
  onWSOpen = function(conn) {
    stopped <- FALSE
    conn$onClose(function() {
      stopped <<- TRUE
    })

    cb <- function(...) {
      if (stopped) {
        return()
      }
      message("sending")
      conn$send(big_string)
    }
    cb()

    conn$onMessage(cb)
  }
)

httpuv::runServer("0.0.0.0", 8101, app)

In the browser on another machine, I navigated to about:blank and typed this code into the JS console:

var ws = new WebSocket("ws://<HOSTNAME>:8101");
ws.onmessage = (msg) => {
  if (!/^j+$/.test(msg.data)) {
    console.log("bad");
  } else {
    console.log("good");
  }
  ws.send("");
};

What this does is repeatedly send large (1MB) messages from server to client, way too big to fit in a single TCP packet. I wanted to ensure that the Ping packets being sent at random times wouldn't get in between packets belonging to a message. The test worked; even hacking the httpuv source code to send Ping every 10 milliseconds didn't pose a problem.