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.
3.5 KiB
einherjar/storage-minio
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
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
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
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)
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
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:
native := s.Native() // *miniogo.Client
Callers that use Native() must import github.com/minio/minio-go/v7 directly.
Error handling
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
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.