Friday, October 08, 2021

How to set up a HTTPS server using cohttp (in O'Caml)

Here is a short tutorial on how to set up a HTTPS server written in O'Caml using cohttp. 

Basically, there is a tutorial on writing a HTTP server in the cohttp package that we start with:


Step I. You prepare a certificate file and a key file using opensl as:

   $ openssl genrsa -out key.pem
   $ openssl req -new -key key.pem -out csr.pem
   $ openssl x509 -req -days 9999 -in csr.pem -signkey key.pem -out cert.pem
   $ rm csr.pem

Step II. You write a server using cohttp with HTTPS mode. 

As a mode for creating a server, 
  • `TCP (`Port 8000) for HTTP
  • `TLS (`Crt_file_path "cert.pem", `Key_file_path "key.pem", `No_password, `Port 8000) for HTTPS
where the port number, file names, and password can be changed for your own purpose. 

$ vi server.ml

#use "topfind";;
#require "lwt";;
#load "unix.cma";;
#load "threads.cma";;
#require "cohttp-lwt-unix";;

open Lwt
open Cohttp
open Cohttp_lwt_unix

let server =
  let callback _conn req body =
    let uri = req |> Request.uri |> Uri.to_string in
    let meth = req |> Request.meth |> Code.string_of_method in
    let headers = req |> Request.headers |> Header.to_string in
    ( body |> Cohttp_lwt.Body.to_string >|= fun body ->
      Printf.sprintf "Uri: %s\nMethod: %s\nHeaders\nHeaders: %s\nBody: %s" uri
        meth headers body )
    >>= fun body -> Server.respond_string ~status:`OK ~body ()
  in
  (* [HTTP] *)
  (*   Lwt_main.run ( Server.create ~mode:(`TCP (`Port 8000)) (Server.make ~callback ())) *)

  (* [HTTPS] *)
  Lwt_main.run ( Server.create ~mode:(`TLS (`Crt_file_path "cert.pem", `Key_file_path "key.pem", `No_password, `Port 8000)) (Server.make ~callback ()))

Step III. Run

$ ocaml -I +threads server.ml

In case you meet errors such as undefined things, you may need to install some packages as:

 $ opam install cohttp-lwt-unix cohttp-async tls lwt