# Providers (https://v2.s3.dimah.dev/docs/providers)

dimah-s3 talks to storage through the AWS SDK `S3Client`. Any service that
speaks enough of the S3 API can work — Amazon S3, Cloudflare R2, MinIO, and
similar backends.

S3-compatible is not the same as Amazon S3. Providers skip or ignore parts of
the API. With a presign-first stack, those gaps show up quickly: the browser
hits storage directly, so CORS, addressing, and the upload method have to
match what the provider actually supports.

| Topic                 | Why it matters                                                                                     |
| --------------------- | -------------------------------------------------------------------------------------------------- |
| Presigned PUT vs POST | Default upload is PUT. POST is opt-in, and some providers have no presigned POST.                  |
| SDK checksums         | The `S3Client` must set `requestChecksumCalculation: "WHEN_REQUIRED"`, or presigned uploads fail.  |
| Object ACL            | `acl: "public-read"` needs real ACL support. Others use bucket policies or a public-access toggle. |
| Endpoint & addressing | Custom endpoints often need `endpoint`, and sometimes `forcePathStyle: true`.                      |
| CORS                  | Browser uploads hit storage directly. The bucket must allow your origin, methods, and headers.     |
| Public URLs           | Public reads may use a CDN, a custom domain, or `*.r2.dev` — not object ACL.                       |

Wire the shared client once in [Quickstart](https://v2.s3.dimah.dev/docs/quickstart). Use the guides
below only for the extras that defaults do not cover.

## Comparison [#comparison]

|                   | [AWS S3](https://v2.s3.dimah.dev/docs/providers/aws-s3) | [Cloudflare R2](https://v2.s3.dimah.dev/docs/providers/cloudflare-r2) | [MinIO](https://v2.s3.dimah.dev/docs/providers/minio) |
| ----------------- | :------------------------------: | :--------------------------------------------: | :----------------------------: |
| Presigned PUT     |          Yes (default)           |                 Yes (default)                  |         Yes (default)          |
| Presigned POST    |               Yes                |                       No                       |              Yes               |
| Object ACL        |               Yes                |                    Ignored                     |          Use policies          |
| Custom `endpoint` |             Optional             |                    Required                    |            Required            |
| `forcePathStyle`  |           Usually off            |                      Off                       |          Typically on          |

## Configuration [#configuration]

```ts
import { S3Client } from "@aws-sdk/client-s3";
import { dimahS3, route } from "@dimah-s3/server";

export const awsS3 = new S3Client({
  // region, endpoint, credentials …
  requestChecksumCalculation: "WHEN_REQUIRED", // [!code ++]
});

export const s3 = dimahS3({
  client: awsS3,
  bucket: process.env.S3_BUCKET!,
  routes: {
    avatar: route({
      upload: { method: "POST" }, // [!code ++]
    }),
  },
});
```

The default upload method is PUT, which every provider here supports. Switch
to POST only when you want a form upload and the provider has presigned POST.
Confirm reports the ACL from `upload.acl` or `object`; there is no
`GetObjectAcl` lookup.

Client hooks and `@dimah-s3/ui` read `method` from the presign response.
Change it on the server only.

## Guides [#guides]

<Cards>
  <Card
    title="Amazon S3"
    href="/docs/providers/aws-s3"
    description="Defaults work. Configure bucket CORS for browser uploads."
  />
  <Card
    title="Cloudflare R2"
    href="/docs/providers/cloudflare-r2"
    description="The R2 endpoint, bucket CORS, and public URLs."
  />
  <Card
    title="MinIO"
    href="/docs/providers/minio"
    description="Path-style addressing and server CORS for self-hosted S3."
  />
</Cards>
