Url Parsing in OCaml

Here’s the translation of the Go URL parsing example to OCaml:

Our URL parsing program demonstrates how to parse URLs in OCaml. URLs provide a uniform way to locate resources.

open Printf
open Unix

(* We'll parse this example URL, which includes a
   scheme, authentication info, host, port, path,
   query params, and query fragment. *)
let s = "postgres://user:pass@host.com:5432/path?k=v#f"

(* Parse the URL and ensure there are no errors. *)
let u = Uri.of_string s

(* Accessing the scheme is straightforward. *)
let () = printf "%s\n" (Uri.scheme u |> Option.value ~default:"")

(* Uri.userinfo contains all authentication info; we need to
   split it manually to get individual username and password. *)
let () =
  match Uri.userinfo u with
  | Some userinfo ->
      printf "%s\n" userinfo;
      (match String.split_on_char ':' userinfo with
       | [username; password] ->
           printf "%s\n%s\n" username password
       | _ -> ())
  | None -> ()

(* The host contains both the hostname and the port,
   if present. Use Uri.host and Uri.port to extract them. *)
let () =
  match Uri.host u, Uri.port u with
  | Some host, Some port ->
      printf "%s:%d\n" host port;
      printf "%s\n%d\n" host port
  | _ -> ()

(* Here we extract the path and the fragment after the #. *)
let () = 
  printf "%s\n" (Uri.path u);
  printf "%s\n" (Uri.fragment u |> Option.value ~default:"")

(* To get query params in a string of k=v format,
   use Uri.query_raw. You can also parse query params
   into a list of key-value pairs using Uri.query. *)
let () =
  (match Uri.query_raw u with
   | Some query -> printf "%s\n" query
   | None -> ());
  let query_params = Uri.query u in
  printf "%s\n" (String.concat ", " (List.map (fun (k, v) -> sprintf "%s: %s" k (String.concat ";" v)) query_params));
  (match List.assoc_opt "k" query_params with
   | Some [v] -> printf "%s\n" v
   | _ -> ())

Running our URL parsing program shows all the different pieces that we extracted.

$ ocaml url_parsing.ml
postgres
user:pass
user
pass
host.com:5432
host.com
5432
/path
f
k=v
k: v
v

In this OCaml version:

  1. We use the Uri module from the uri library to parse the URL.
  2. The Uri.of_string function is used to parse the URL string.
  3. We use pattern matching and the Option module to handle optional values.
  4. The Uri module doesn’t provide a direct way to split the userinfo, so we manually split it.
  5. We use Uri.query to get the query parameters as a list of key-value pairs.

Note that OCaml’s standard library doesn’t include URL parsing functionality, so you would need to install and use a third-party library like uri for this example to work. The exact API might vary depending on the version of the library used.