The package-doc examples showed a fictional launcher.Register / health.Register API (and launcher.Append as a package func). Corrected to the real wiring: lc.Append + web/health.NewHandler(...).ServeHTTP. Documentation-only. No code, API, or dependency changes; version stays v1.1.0 (the v1.1.0 tag is moved to include this fix). Verified by compiling the corrected pattern against the real API.
127 lines
3.5 KiB
Markdown
127 lines
3.5 KiB
Markdown
# einherjar/storage-minio
|
|
|
|
[](https://code.nochebuena.dev/einherjar/storage-minio)
|
|
[](LICENSE)
|
|
[](https://go.dev)
|
|
[]()
|
|
|
|
> The shield does not care who forged it. It holds what it is given and gives it back unchanged.
|
|
|
|
`code.nochebuena.dev/einherjar/storage-minio` is the MinIO/S3 object storage component of the Einherjar framework. It wraps `minio-go/v7` behind a lifecycle-aware `Component` with four common operations — upload, download, delete, and presigned URLs. For anything beyond that scope, `Native()` returns the raw `*miniogo.Client`.
|
|
|
|
---
|
|
|
|
## Usage
|
|
|
|
### Setup
|
|
|
|
```go
|
|
import storageminio "code.nochebuena.dev/einherjar/storage-minio"
|
|
|
|
s := storageminio.New(logger, storageminio.DefaultConfig())
|
|
lc.Append(s) // OnInit connects; OnStop is a no-op (stateless client)
|
|
// s is observability.Checkable (BucketExists check, LevelCritical):
|
|
srv.Get("/health", health.NewHandler(logger, s).ServeHTTP)
|
|
```
|
|
|
|
### Uploading
|
|
|
|
```go
|
|
import miniogo "github.com/minio/minio-go/v7"
|
|
|
|
info, err := s.PutObject(ctx, "my-bucket", "uploads/photo.jpg", reader, size, miniogo.PutObjectOptions{
|
|
ContentType: "image/jpeg",
|
|
})
|
|
```
|
|
|
|
### Downloading
|
|
|
|
```go
|
|
obj, err := s.GetObject(ctx, "my-bucket", "uploads/photo.jpg", miniogo.GetObjectOptions{})
|
|
if err != nil {
|
|
return s.HandleError(err)
|
|
}
|
|
defer obj.Close()
|
|
```
|
|
|
|
### Presigned URL (time-limited public access)
|
|
|
|
```go
|
|
url, err := s.PresignedGetObject(ctx, "my-bucket", "uploads/photo.jpg", 15*time.Minute, nil)
|
|
// url is a *url.URL — call url.String() to get the string form
|
|
```
|
|
|
|
### Deleting
|
|
|
|
```go
|
|
err := s.RemoveObject(ctx, "my-bucket", "uploads/photo.jpg", miniogo.RemoveObjectOptions{})
|
|
```
|
|
|
|
### Native escape hatch
|
|
|
|
For multipart uploads, bucket management, or any operation not in `Provider`, use the raw client:
|
|
|
|
```go
|
|
native := s.Native() // *miniogo.Client
|
|
```
|
|
|
|
Callers that use `Native()` must import `github.com/minio/minio-go/v7` directly.
|
|
|
|
### Error handling
|
|
|
|
```go
|
|
if err := s.HandleError(someErr); err != nil {
|
|
// minio-go error responses mapped to xerrors:
|
|
// NoSuchKey / NoSuchBucket → ErrNotFound
|
|
// AccessDenied → ErrPermissionDenied
|
|
// context.Canceled → ErrCancelled
|
|
// context.DeadlineExceeded → ErrDeadlineExceeded
|
|
}
|
|
```
|
|
|
|
`HandleError` is also available as a package-level function: `storageminio.HandleError(err)`.
|
|
|
|
---
|
|
|
|
## Environment variables
|
|
|
|
| Variable | Required | Default | Description |
|
|
|---|---|---|---|
|
|
| `EINHERJAR_MINIO_ENDPOINT` | Yes | — | MinIO/S3 endpoint (host:port or domain) |
|
|
| `EINHERJAR_MINIO_ACCESS_KEY` | Yes | — | Access key ID |
|
|
| `EINHERJAR_MINIO_SECRET_KEY` | Yes | — | Secret access key |
|
|
| `EINHERJAR_MINIO_BUCKET` | Yes | — | Default bucket for health check |
|
|
| `EINHERJAR_MINIO_USE_SSL` | No | `false` | Use TLS |
|
|
| `EINHERJAR_MINIO_REGION` | No | `us-east-1` | Bucket region |
|
|
|
|
---
|
|
|
|
## Dependency graph
|
|
|
|
```
|
|
contracts (zero dependencies)
|
|
↑
|
|
core
|
|
↑
|
|
storage-minio (contracts, core, minio-go/v7)
|
|
↑
|
|
your app
|
|
```
|
|
|
|
---
|
|
|
|
## Verification
|
|
|
|
```bash
|
|
cd storage-minio/
|
|
go build ./...
|
|
go vet ./...
|
|
go test ./...
|
|
gofmt -l .
|
|
```
|
|
|
|
---
|
|
|
|
> *The artifact survives the battle that created it.*
|
|
> *Store it well. Someone will need it after you are gone.*
|