My aggregated monorepo of OCaml code, automaintained
1(*---------------------------------------------------------------------------
2 Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
3 SPDX-License-Identifier: ISC
4 ---------------------------------------------------------------------------*)
5
6(** HTTP client using the requests library *)
7
8let src = Logs.Src.create "bushel.http" ~doc:"HTTP client"
9module Log = (val Logs.src_log src : Logs.LOG)
10
11type t = Requests.t
12
13let create ~sw env =
14 Requests.create ~sw ~follow_redirects:true env
15
16let get ~http url =
17 Log.debug (fun m -> m "GET %s" url);
18 try
19 let response = Requests.get http url in
20 if Requests.Response.ok response then begin
21 let body = Requests.Response.body response |> Eio.Flow.read_all in
22 Ok body
23 end else begin
24 let status = Requests.Response.status_code response in
25 Error (Printf.sprintf "HTTP %d" status)
26 end
27 with exn ->
28 Error (Printf.sprintf "Request failed: %s" (Printexc.to_string exn))
29
30let get_with_header ~http ~header url =
31 Log.debug (fun m -> m "GET %s (with header)" url);
32 try
33 (* Parse header "Name: Value" format *)
34 let name, value = match String.index_opt header ':' with
35 | Some i ->
36 let name = String.sub header 0 i in
37 let value = String.trim (String.sub header (i + 1) (String.length header - i - 1)) in
38 (name, value)
39 | None -> (header, "")
40 in
41 let headers = Requests.Headers.empty |> Requests.Headers.add_string name value in
42 let response = Requests.get http ~headers url in
43 if Requests.Response.ok response then begin
44 let body = Requests.Response.body response |> Eio.Flow.read_all in
45 Ok body
46 end else begin
47 let status = Requests.Response.status_code response in
48 Error (Printf.sprintf "HTTP %d" status)
49 end
50 with exn ->
51 Error (Printf.sprintf "Request failed: %s" (Printexc.to_string exn))
52
53let post ~http ~content_type ~body url =
54 Log.debug (fun m -> m "POST %s" url);
55 try
56 let mime = Requests.Mime.of_string content_type in
57 let body = Requests.Body.of_string mime body in
58 let response = Requests.post http ~body url in
59 if Requests.Response.ok response then begin
60 let body = Requests.Response.body response |> Eio.Flow.read_all in
61 Ok body
62 end else begin
63 let status = Requests.Response.status_code response in
64 Error (Printf.sprintf "HTTP %d" status)
65 end
66 with exn ->
67 Error (Printf.sprintf "Request failed: %s" (Printexc.to_string exn))