package picos_io_cohttp

  1. Overview
  2. Docs
Cohttp running on Picos IO

Install

Dune Dependency

Authors

Maintainers

Sources

picos-0.5.0.tbz
sha256=862d61383e2df93a876bedcffb1fd1ddc0f96c50b0e9c07943a2aee1f0e182be
sha512=87805379017ef4a7f2c11b954625a3757a0f1431bb9ba59132202de278b3e41adbe0cdc20e3ab23b7c9a8c5a15faeb7ec79348e7d80f2b14274b00df0893b8c0

doc/picos_io_cohttp/Picos_io_cohttp/index.html

Module Picos_io_cohttpSource

Minimalistic Cohttp implementation using Picos_io for Picos.

⚠️ This library is currently minimalistic and experimental and is highly likely to change. Feedback from potential users is welcome!

Modules

Sourcemodule Client : sig ... end

Convenience functions for constructing requests and processing responses.

Sourcemodule Server : sig ... end

Convenience functions for processing requests and constructing responses.

Examples

First we open some modules for convenience:

  open Cohttp
  open Picos_io
  open Picos_io_cohttp
  open Picos_std_finally
  open Picos_std_structured

A server and client

Let's build a simple hello server. We first define a function that creates and configures a socket for the server:

  let server_create ?(max_pending_reqs = 8) addr =
    let socket =
      Unix.socket ~cloexec:true PF_INET SOCK_STREAM 0
    in
    match
      Unix.set_nonblock socket;
      Unix.bind socket addr;
      Unix.listen socket max_pending_reqs
    with
    | () -> socket
    | exception exn ->
      Unix.close socket;
      raise exn

The reason for doing it like this, as we'll see later, is that we want the OS to decide the port for our server. Also note that we explicitly set the socket to non-blocking mode, which is what we should do with Picos_io whenever possible.

Then we'll define a function that runs a server given a socket:

  let server_run socket =
    let callback _conn _req body =
      let body =
        Printf.sprintf "Hello, %s!"
          (Body.to_string body)
      in
      Server.respond_string ~status:`OK ~body ()
    in
    Server.run (Server.make ~callback ()) socket

The idea is that the body of the request is the name to be greeted in the body of the response.

A client then posts to the specified uri and returns the response body:

  let client uri name =
    let resp, body =
      Client.post ~body:(`String name) uri
    in
    if Response.status resp != `OK then
      failwith "Not OK";
    Body.to_string body

Now we are ready to put everything together:

  # Picos_mux_random.run_on ~n_domains:2 @@ fun () ->

    let@ server_socket =
      finally Unix.close @@ fun () ->
      server_create
        Unix.(ADDR_INET (inet_addr_loopback, 0))
    in

    let server_port =
      match Unix.getsockname server_socket with
      | ADDR_UNIX _ -> failwith "impossible"
      | ADDR_INET (_, port) -> port
    in

    let server_uri =
      Uri.make
        ~scheme:"http"
        ~host:"127.0.0.1"
        ~port:server_port
        ()
    in

    Flock.join_after ~on_return:`Terminate @@ fun () ->

    Flock.fork begin fun () ->
      server_run server_socket
    end;

    client server_uri "World"
  - : string = "Hello, World!"

We first create the server_socket and obtain the server_port and ultimately the server_uri from it — typically one can avoid this complexity and use a fixed port. We then create a flock for running the server as a concurrent fiber, which we arrange to terminate at the end of the scope. Finally we act as the client to get a greeting from the server.

OCaml

Innovation. Community. Security.