How to write a simple socket-based web client (for Docker)

You almost had it – just need to create a custom resolver in order to map a hostname into a Unix domain socket. There is no standard way to do this in HTTP (something has to be present in the Host field in HTTP/1.1), so we just make up a name like docker.

open Lwt.Infix

let t =
  let resolver =
    let h = Hashtbl.create 1 in
    Hashtbl.add h "docker" (`Unix_domain_socket "/var/run/docker.sock");
    Resolver_lwt_unix.static h in
  let ctx = Cohttp_lwt_unix.Client.custom_ctx ~resolver () in
  Cohttp_lwt_unix.Client.get ~ctx (Uri.of_string "http://docker/version") >>= fun (resp, body) ->
  let open Cohttp in
  let code = resp |> Response.status |> Code.code_of_status in
  Printf.printf "Response code: %d\n" code;
  Printf.printf "Headers: %s\n" (resp |> Response.headers |> Header.to_string);
  body |> Cohttp_lwt.Body.to_string >|= fun body ->
  Printf.printf "Body of length: %d\n" (String.length body);
  print_endline ("Received body\n" ^ body)

let _ = Lwt_main.run t

Run this with CONDUIT_DEBUG=1 in the environment and I get:

Resolver static: http://docker/version ((name http) (port 80) (tls false)) -> (Unix_domain_socket /var/run/docker.sock)
Response code: 200
Headers: api-version: 1.37
content-length: 574
content-type: application/json
date: Fri, 23 Mar 2018 17:27:32 GMT
docker-experimental: true
ostype: linux
server: Docker/18.03.0-ce-rc4 (linux)


Body of length: 574
Received body
{"Platform":{"Name":""},"Components":[{"Name":"Engine","Version":"18.03.0-ce-rc4","Details":{"ApiVersion":"1.37","Arch":"amd64","BuildTime":"2018-03-15T07:42:29.000000000+00:00","Experimental":"true","GitCommit":"fbedb97","GoVersion":"go1.9.4","KernelVersion":"4.9.87-linuxkit-aufs","MinAPIVersion":"1.12","Os":"linux"}}],"Version":"18.03.0-ce-rc4","ApiVersion":"1.37","MinAPIVersion":"1.12","GitCommit":"fbedb97","GoVersion":"go1.9.4","Os":"linux","Arch":"amd64","KernelVersion":"4.9.87-linuxkit-aufs","Experimental":true,"BuildTime":"2018-03-15T07:42:29.000000000+00:00"}
2 Likes