···11+ISC License
22+33+Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>
44+55+Permission to use, copy, modify, and distribute this software for any
66+purpose with or without fee is hereby granted, provided that the above
77+copyright notice and this permission notice appear in all copies.
88+99+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1010+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1111+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1212+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1313+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1414+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1515+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+70
README.md
···11+# requests - HTTP Client Library for OCaml
22+33+A modern HTTP(S) client library for OCaml with Eio support, providing a clean API for making web requests with automatic TLS/CA certificate handling. Inspired by Python's requests library.
44+55+## Key Features
66+77+- **Clean Eio-style API**: Async I/O using OCaml 5's Eio library
88+- **Automatic TLS**: Built-in TLS support with automatic CA certificate handling
99+- **Simple Interface**: Intuitive API similar to Python's requests library
1010+- **Type-safe**: Leverages OCaml's type system for safer HTTP operations
1111+- **Comprehensive**: Support for common HTTP methods, headers, authentication, retries, and timeouts
1212+1313+## Usage
1414+1515+Basic GET request:
1616+1717+```ocaml
1818+let () =
1919+ Eio_main.run @@ fun env ->
2020+ let response = Requests.get ~env (Uri.of_string "https://example.com") in
2121+ print_endline (Requests.Response.body_string response)
2222+```
2323+2424+POST request with JSON body:
2525+2626+```ocaml
2727+let () =
2828+ Eio_main.run @@ fun env ->
2929+ let uri = Uri.of_string "https://api.example.com/data" in
3030+ let body = {|{"key": "value"}|} in
3131+ let headers = Requests.Headers.of_list [
3232+ ("content-type", "application/json")
3333+ ] in
3434+ let response = Requests.post ~env ~headers ~body uri in
3535+ Printf.printf "Status: %d\n" (Requests.Response.status_code response)
3636+```
3737+3838+Using authentication and custom headers:
3939+4040+```ocaml
4141+let () =
4242+ Eio_main.run @@ fun env ->
4343+ let auth = Requests.Auth.basic ~username:"user" ~password:"pass" in
4444+ let headers = Requests.Headers.add
4545+ (Requests.Headers.init ())
4646+ "user-agent" "my-app/1.0" in
4747+ let response = Requests.get ~env ~auth ~headers
4848+ (Uri.of_string "https://api.example.com") in
4949+ (* Process response *)
5050+ ()
5151+```
5252+5353+## Installation
5454+5555+```
5656+opam install requests
5757+```
5858+5959+## Documentation
6060+6161+API documentation is available at https://tangled.org/@anil.recoil.org/ocaml-requests or via:
6262+6363+```
6464+opam install requests
6565+odig doc requests
6666+```
6767+6868+## License
6969+7070+ISC
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(** Authentication mechanisms *)
2738(** Log source for authentication operations *)
+6-1
lib/body.ml
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16let src = Logs.Src.create "requests.body" ~doc:"HTTP Request/Response Body"
27module Log = (val Logs.src_log src : Logs.LOG)
38···6368(* JSON streaming using jsont - we encode the value to string and stream it *)
6469module Json_stream_source = struct
6570 type t = {
6666- mutable content : string;
7171+ content : string;
6772 mutable offset : int;
6873 }
6974
+5
lib/body.mli
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(** HTTP request body construction
2738 This module provides various ways to construct HTTP request bodies,
+5
lib/error.ml
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(** Centralized error handling for the Requests library *)
2738let src = Logs.Src.create "requests.error" ~doc:"HTTP Request Errors"
+5
lib/error.mli
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(** Centralized error handling for the Requests library *)
2738(** Log source for error reporting *)
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(** HTTP headers management with case-insensitive keys
2738 This module provides an efficient implementation of HTTP headers with
+5
lib/http_client.ml
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(** Low-level HTTP/1.1 client over raw TCP connections for connection pooling *)
2738let src = Logs.Src.create "requests.http_client" ~doc:"Low-level HTTP client"
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(** One-shot HTTP client for stateless requests
2738 The One module provides a stateless HTTP client for single requests without
+5
lib/requests.ml
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(** OCaml HTTP client library with streaming support *)
2738let src = Logs.Src.create "requests" ~doc:"HTTP Client Library"
+5
lib/requests.mli
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(** Requests - A modern HTTP client library for OCaml
2738 Requests is an HTTP client library for OCaml inspired by Python's requests
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(** HTTP request retry logic with exponential backoff *)
2738open Eio
+5
lib/status.ml
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(** HTTP status codes following RFC 7231 and extensions *)
2738let src = Logs.Src.create "requests.status" ~doc:"HTTP Status Codes"
+5
lib/status.mli
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(** HTTP status codes following RFC 7231 and extensions *)
2738(** Log source for status code operations *)
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(** Timeout configuration *)
2738(** Log source for timeout operations *)
+11-9
requests.opam
···22opam-version: "2.0"
33synopsis: "Clean Eio-style HTTPS client library for OCaml"
44description:
55- "A modern HTTP(S) client library for OCaml with Eio support, providing a clean API for making web requests with automatic TLS/CA certificate handling"
66-maintainer: ["Your Name"]
77-authors: ["Your Name"]
88-license: "MIT"
99-homepage: "https://github.com/username/requests"
1010-bug-reports: "https://github.com/username/requests/issues"
55+ "A modern HTTP(S) client library for OCaml with Eio support, providing a clean API for making web requests with automatic TLS/CA certificate handling. Inspired by Python's requests library, this provides a simple, intuitive interface for HTTP operations."
66+maintainer: ["Anil Madhavapeddy <anil@recoil.org>"]
77+authors: ["Anil Madhavapeddy"]
88+license: "ISC"
99+homepage: "https://tangled.org/@anil.recoil.org/ocaml-requests"
1010+bug-reports: "https://tangled.org/@anil.recoil.org/ocaml-requests/issues"
1111depends: [
1212- "ocaml"
1313- "dune" {>= "3.0" & >= "3.0"}
1212+ "ocaml" {>= "5.1.0"}
1313+ "dune" {>= "3.20" & >= "3.20"}
1414 "eio"
1515 "cohttp-eio"
1616 "tls-eio"
···2121 "base64"
2222 "logs"
2323 "odoc" {with-doc}
2424+ "alcotest" {with-test & >= "1.7.0"}
2525+ "eio_main" {with-test}
2426]
2527build: [
2628 ["dune" "subst"] {dev}
···3638 "@doc" {with-doc}
3739 ]
3840]
3939-dev-repo: "git+https://github.com/username/requests.git"
4141+x-maintenance-intent: ["(latest)"]
+5
test/test_localhost.ml
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(* Test conpool with 16 localhost servers on different 127.0.* addresses *)
2738open Eio.Std
+5
test/test_localhost.mli
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+
+5
test/test_simple.ml
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+16(* Simple test to debug connection issues *)
2738open Eio.Std
+5
test/test_simple.mli
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+