awskit-s3

AWS S3 client for bucket and object storage, multipart uploads, presigned request artifacts, and the supported bucket/object scope documented in S3 Support Matrix and SUPPORT.md.

See awskit for the pure core and runtime adapter overview.

The main entrypoint is Awskit_s3. Advanced application APIs such as streaming bodies, scoped readers, presigning, multipart upload, endpoint configuration, retry, timeout, and transfer helpers are normal SDK APIs. Protocol encoders, protocol parsers, response helpers, and other implementation modules are private unless they are deliberately documented as public.

Security reporting and sensitive-data handling are documented in SECURITY.md.

Client Surface

awskit-s3 provides S3 operations for bucket and object storage applications:

Bucket policy operations accept validated JSON policy documents. This lets applications use their own policy model while Awskit handles S3 request construction and response handling.

API Shape

Object APIs are split into explicit layers:

Small buffered object workflows can start with Object.put_string, Object.put_bytes, Object.get_string, Object.get_bytes, Object.find_string, and Object.find_bytes. Larger or custom workflows pass Body values to Object.put and scoped Reader consumers to Object.get. Direct Runtime access remains available for integrations and runtime authors that need the raw runtime body layer.

Managed local-file transfers are adapter features, not core S3 features. They live in Object.Transfer for awskit-s3-eio and awskit-s3-lwt-unix. The generic awskit-s3-lwt package exposes streaming body and reader primitives over a caller-supplied Lwt HTTP backend, but it does not own Unix paths or managed transfer helpers.

Libraries

awskit-s3

Awskit_s3 contains runtime-agnostic S3 types, endpoint configuration, standalone presigned request artifact helpers, and the runtime functor.

Main modules:

awskit-s3-sim

Awskit_s3_sim provides a deterministic in-memory S3 implementation for tests. It implements the same synchronous S3 operation shape as runtime-backed clients and adds a controllable clock, store inspection, operation history, and fault injection. It is not live AWS coverage and is not a wire-protocol authority.

awskit-s3-eio

Awskit_s3_eio provides a direct-style Eio adapter over a caller-owned HTTPS policy. Applications own TLS configuration, CA roots, RNG initialization, and platform policy. Operations return plain results. It also exposes local-path helpers under Body and Reader, plus managed local-file helpers under Object.Transfer. Examples that call Awskit_unix also need the awskit-unix package, but awskit-s3-eio itself does not provide a ready Eio Unix aggregate adapter.

awskit-s3-lwt

Awskit_s3_lwt provides a functor over Cohttp_lwt.S.Client. Operations return Lwt.t. It is the right package for custom Lwt HTTP backends; use awskit-s3-lwt-unix for Unix local-path body, reader, and managed transfer helpers.

awskit-s3-lwt-unix

Awskit_s3_lwt_unix provides the ready-to-use Lwt + Unix adapter. It can read credentials and region from the standard AWS environment variables through the underlying awskit-lwt-unix runtime. It exposes local-path helpers under Body and Reader, plus managed local-file helpers under Object.Transfer.

Minimal Eio Example

open Eio.Std

module Https = struct
  let connector () =
    Mirage_crypto_rng_unix.use_default ();
    let authenticator =
      match Ca_certs.authenticator () with
      | Ok authenticator -> authenticator
      | Error (`Msg msg) -> invalid_arg ("failed to load CA roots: " ^ msg)
    in
    let tls_config =
      match Tls.Config.client ~authenticator () with
      | Ok config -> config
      | Error (`Msg msg) -> invalid_arg ("failed to create TLS config: " ^ msg)
    in
    Some
      (fun uri raw ->
        let host =
          match Uri.host uri with
          | Some host -> Domain_name.host_exn (Domain_name.of_string_exn host)
          | None -> invalid_arg "HTTPS URI is missing a host"
        in
        (Tls_eio.client_of_flow tls_config ~host raw
          :> [ Eio.Flow.two_way_ty | Eio.Resource.close_ty ] Eio.Flow.two_way))
end

let run env =
  Switch.run @@ fun sw ->
  let credentials =
    Awskit_unix.Credentials.default_chain ()
    |> Result.get_ok
  in
  let https = Https.connector () in
  match
    Awskit_s3_eio.create ~sw ~env ~https ~region:"us-east-1" ~credentials ()
  with
  | Error err -> Fmt.epr "%a@." Awskit_s3.Error.pp err
  | Ok s3 -> (
      let bucket = Awskit_s3.Bucket_name.of_string_exn "my-bucket" in
      let key = Awskit_s3.Object_key.of_string_exn "hello.txt" in
      match
        Awskit_s3_eio.Object.put_string s3
          ~bucket
          ~key
          ~contents:"Hello, S3!"
          ()
      with
      | Ok _ -> ()
      | Error err -> Fmt.epr "%a@." Awskit_s3.Error.pp err)

Minimal Lwt Unix Example

let run () =
  let open Lwt.Syntax in
  match Awskit_s3_lwt_unix.create () with
  | Error err ->
      Lwt_io.eprintf "%s\n" (Awskit_s3.Error.to_string_hum err)
  | Ok s3 ->
      let bucket = Awskit_s3.Bucket_name.of_string_exn "my-bucket" in
      let key = Awskit_s3.Object_key.of_string_exn "hello.txt" in
      let* result =
        Awskit_s3_lwt_unix.Object.get_string s3
          ~bucket
          ~key
          ~max_bytes:1_048_576L
          ()
      in
      match result with
      | Ok result -> Lwt_io.printl result.value
      | Error err -> Lwt_io.eprintf "%a\n" Awskit_s3.Error.pp err

Guides