Opium & Lwt usage and questions

Hello,
I am porting a project previously based on a synchronous nethttpd server to Opium.
I’d first like to thank @rgrinberg for Opium, which is so much easier to set up than nethttpd :). Since I am not much used to event programming or Lwt, I have some questions.

  • First question: When receiving e.g. a POST request with a body, the body seems to come as a string Lwt_stream.t. Is there a “good way” to work with such body ? I could come with two ways, both using Lwt_main.run:

        let body = req.body
          |> Cohttp_lwt.Body.to_string
          |> Lwt_main.run
       ... use body variable
    
        (
         match%lwt
         req.body
         |> Cohttp_lwt.Body.to_string
         >|= Yojson.Safe.from_string 
         >|= my_type_of_yojson
         with
          | Ok res -> Lwt.return "body decoded"
          | Error e -> Lwt.return "bad body"
        )
        |>  Lwt_main.run
    
  • Second question: the web server provides an interface to a kind of simulator, that is an object that is not designed to be accessed concurrently. Will Mutex be enough to deal with this, or is there anything else i should know ?

Edit:

  • Third question (altough I guess I would eventually find out): I am using my own command line arguments, so I don’t use Opium’s built in. I did not see an easy way to pass e.g. the debug argument for the Opium App, is there one ?

Ok so I found out the answer for my first question.

What I was trying to achieve was the following:

open Lwt.Infix
open Opium.Std

let build (req: Opium_kernel__Rock.Request.t) =
  (
    match%lwt
      req.body
      |> Cohttp_lwt.Body.to_string
      >|= Yojson.Safe.from_string 
      >|= build_req_body_of_yojson
    with
    | Ok res -> Lwt.return (`String "body decoded")
    | Error e -> Lwt.return (`String ("bad body"^e))
  )


let start_srv () = 
App.empty
 |> post "/api/utils/build" (fun x -> (build x) >|=  respond)
 |> App.run_command 

There is no limit to the size of the post request. I fear your server would run out of memory if you receive 2GB of data…

Hmm that’s right. My server is not supposed to be exposed to a broad public, but I should think of input sanitizing nonetheless.

All your Lwt code will run in the main thread. This means that once you call a function in your simulator object’s API, that function will run to completion without any interference from anything else that needs to run later in the main thread, like processing more requests with Opium, or running anything else that is using Lwt.

So, you only need a mutex if you need to protect a sequence of two or more calls to the simulator object’s API. Even then, you only need a mutex if your code does an Lwt bind between those two calls.

If that’s the case, consider Lwt_mutex.

The standard Mutex is wrong here, because it prevents interference between different system threads, while, again, all Lwt code runs in the main thread.

Slightly off topic but I would be interested to look at a small web app that uses Opium where the HTML is handled client side and not generated by the server. Looking trough Opam I could not find one, the Opium repo does not list any, and its examples are a bit too minimal.

I don’t have a specific example with Opium but you can have a client side driven app by serving your Javascript file using opium’s static file serving middleware.

After that any of the client side examples should be application. You could use tyxml with jsoo, incr_dom, ocaml-vdom, or any javascript client side solution.