Awskit is AWS infrastructure for OCaml.
It provides the pieces needed to build AWS clients in OCaml: credentials, regions, endpoints, SigV4 signing, retry handling, request and response types, runtime adapters, and S3 support. The core packages are pure OCaml; concrete HTTP execution lives in runtime-specific adapter packages for Eio and Lwt.
Awskit currently focuses on AWS S3.
- Pure AWS core types, signing, endpoints, credentials, errors, and retries.
- Runtime adapters for Eio and Lwt applications.
- S3 bucket, object, multipart upload, policy, tagging, versioning, and presigned URL support.
- Streaming request and response bodies with explicit replayability metadata.
- Deterministic in-memory S3 simulator for tests.
- Unix helpers for standard AWS environment variables, shared credentials, and config files.
Awskit is split into small packages. From a source checkout, install dependencies and build with Dune:
opam install . --deps-only --with-test
opam exec -- dune buildWhen installing released packages from opam, install the adapter that matches your runtime:
opam install awskit-s3-eioor:
opam install awskit-s3-lwt-unix| Package | Description |
|---|---|
awskit |
Pure AWS core: credentials, regions, endpoints, SigV4 signing, retries, request/response types, errors, and the runtime module type. |
awskit-unix |
Unix helpers for clocks, environment variables, shared AWS credentials, and config files. |
awskit-lwt |
Generic Lwt runtime adapter over a caller-supplied Cohttp Lwt client. |
awskit-lwt-unix |
Ready-to-use Lwt + Unix runtime adapter using Cohttp Lwt Unix. |
awskit-eio |
Ready-to-use direct-style Eio runtime adapter using Cohttp Eio. |
awskit-s3 |
Pure AWS S3 core: buckets, objects, multipart upload, presigned URLs, policies, endpoint resolution, and simulator. |
awskit-s3-lwt |
S3 adapter over the generic Awskit Lwt runtime. |
awskit-s3-lwt-unix |
Ready-to-use S3 client for Lwt + Unix applications. |
awskit-s3-eio |
Ready-to-use S3 client for Eio applications. |
The awskit and awskit-s3 packages do not depend on Unix, Eio, Lwt, or
Cohttp runtime packages. Adapter packages carry those runtime dependencies.
Install the Eio S3 adapter:
opam install awskit-s3-eio eio_mainAdd the libraries to your Dune file:
; dune
(libraries awskit awskit-s3 awskit-s3-eio eio_main fmt)Upload an object:
open Eio.Std
let () =
Eio_main.run @@ fun env ->
Switch.run @@ fun sw ->
let credentials =
Awskit.Credentials.create_exn
~access_key_id:"AKIAIOSFODNN7EXAMPLE"
~secret_access_key:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
()
in
let region = Awskit.Region.of_string_exn "us-east-1" in
let s3 = Awskit_s3_eio.create ~sw ~env ~region ~credentials () in
match
Awskit_s3_eio.Object.put_string s3
~bucket:"my-bucket"
~key:"hello.txt"
"Hello, S3!"
with
| Ok uploaded ->
Fmt.pr "Uploaded. ETag: %a@."
(Fmt.option Awskit_s3.Object.Etag.pp)
uploaded.etag
| Error error -> Fmt.epr "S3 error: %a@." Awskit_s3.Error.pp errorInstall the Lwt Unix S3 adapter:
opam install awskit-s3-lwt-unixAdd the libraries to your Dune file:
; dune
(libraries awskit awskit-s3 awskit-s3-lwt-unix lwt.unix)Download an object:
open Lwt.Syntax
let run () =
match Awskit_s3_lwt_unix.create () with
| Error error -> Lwt_io.eprintf "S3 error: %a\n" Awskit_s3.Error.pp error
| Ok s3 ->
let* result =
Awskit_s3_lwt_unix.Object.get_as_string s3
~bucket:"my-bucket"
~key:"hello.txt"
~max_bytes:1_048_576L
()
in
match result with
| Ok (_info, body) -> Lwt_io.printl body
| Error error -> Lwt_io.eprintf "S3 error: %a\n" Awskit_s3.Error.pp errorWhen arguments are omitted, the Unix adapter reads standard AWS configuration sources:
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_SESSION_TOKEN
AWS_REGION
AWS_DEFAULT_REGION
AWS_PROFILE
AWS_SHARED_CREDENTIALS_FILE
AWS_CONFIG_FILE
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
AWS_CONTAINER_CREDENTIALS_FULL_URI
AWS_CONTAINER_AUTHORIZATION_TOKEN
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE
Pass an explicit endpoint when testing against a local service or custom AWS
endpoint.
awskit-s3 exposes AWS S3 operations for:
- bucket creation, deletion, listing, and configuration;
- object put, get, head, delete, copy, ranges, metadata, tags, and versions;
- multipart upload and local-file transfer helpers;
- presigned URLs;
- bucket policies and related XML/JSON wire types;
- S3 endpoint and addressing configuration;
- structured S3 error classifiers;
- deterministic in-memory simulation for tests.
Awskit targets AWS S3 semantics. S3-compatible services such as MinIO are useful for local contract testing, but provider-specific behavior should stay in tests unless it matches AWS S3.
S3 supports virtual-hosted and path-style bucket addressing. Awskit exposes this as:
type addressing_style = [ `Auto | `Path | `Virtual_hosted ]Auto uses virtual-hosted addressing when the bucket and endpoint support it,
and falls back to path-style otherwise. Local test services commonly need
~addressing_style:Path`.
Runtime request bodies carry a descriptor with content_length,
payload_hash, and replayable metadata. S3 PutObject and UploadPart
currently require a known content_length; Awskit does not implement
unknown-length SigV4 aws-chunked streaming.
For already-buffered data, prefer string or bytes body helpers. Custom stream bodies must emit exactly the declared number of bytes, and producer callback errors are reported as request body failures. Mark custom streams replayable only when the stream can actually be replayed for a retry.
Response bodies are streaming and scoped to the runtime response callback.
Runtime adapters expose with_response; inside that callback, consume bodies
through Response_body.with_reader or S3 helper APIs such as
Object.get_as_string ~max_bytes.
The simulator provides deterministic in-memory S3 for unit tests. It does not require network access or AWS credentials.
let () =
let credentials =
Awskit.Credentials.create_exn
~access_key_id:"AK"
~secret_access_key:"SK"
()
in
let clock = Awskit_s3.Simulator.Clock.create () in
let store = Awskit_s3.Simulator.create_store ~clock () in
let conn = Awskit_s3.Simulator.connect store ~credentials in
Awskit_s3.Simulator.Bucket.create conn ~bucket:"test" () |> ignore;
Awskit_s3.Simulator.Object.put_string conn
~bucket:"test"
~key:"hello"
"world"
|> ignoreInstall dependencies and run the build and test suite:
opam install . --deps-only --with-test
opam exec -- dune build
opam exec -- dune testOptional MinIO contract tests:
docker compose up -d
opam exec -- dune build @minio-contractThe MinIO contract runner defaults to http://127.0.0.1:9000 with the
minioadmin credentials from docker-compose.yml. Override with:
AWSKIT_S3_MINIO_ENDPOINT
AWSKIT_S3_MINIO_ACCESS_KEY_ID
AWSKIT_S3_MINIO_SECRET_ACCESS_KEY
AWSKIT_S3_MINIO_REGION
Issues and pull requests are welcome. For code changes, please run:
opam exec -- dune build
opam exec -- dune testKeep changes focused, include tests for behavior changes, and prefer the existing package split when adding new runtime-specific functionality.
MIT. See LICENSE.