Documentation
¶
Index ¶
- Constants
- Variables
- func CheckPreconditions(etag string, modTime time.Time, opts GetOptions) error
- func EscapeURLPath(key string) string
- func FormatError(err error) string
- func IsNotFound(err error) bool
- func IsObjectLocked(err error) bool
- func IsPermanent(err error) bool
- func IsPermissionDenied(err error) bool
- func IsPreconditionFailed(err error) bool
- func IsProviderUnavailable(err error) bool
- func IsQuotaExceeded(err error) bool
- func IsRateLimited(err error) bool
- func IsSecurityViolation(err error) bool
- func IsTransient(err error) bool
- func NewErrorf(op, key, provider, format string, a ...any) error
- func PreserveSentinel(err error) bool
- func ResolvePayload(r io.Reader, opts PutOptions) (io.Reader, int64, bool, error)
- func SanitizeErrorMessage(raw string) string
- func SanitizeFilename(raw string) string
- func SanitizeHeader(raw string) string
- func ValidateKey(key string) error
- func WrapError(op, key, provider string, err error) error
- type BaseDriver
- func (b *BaseDriver) AbortMultipart(ctx context.Context, key string, uploadID string) error
- func (b *BaseDriver) Capabilities() Capability
- func (b *BaseDriver) Close() error
- func (b *BaseDriver) CompleteMultipart(ctx context.Context, obj *Object, uploadID string, parts []CompletedPart) (*Object, error)
- func (b *BaseDriver) Copy(ctx context.Context, srcKey, dstKey string) error
- func (b *BaseDriver) CreateMultipart(ctx context.Context, obj *Object, opts PutOptions) (string, error)
- func (b *BaseDriver) Delete(ctx context.Context, key string) error
- func (b *BaseDriver) DeleteBatch(ctx context.Context, keys []string) ([]string, error)
- func (b *BaseDriver) Get(ctx context.Context, key string, opts GetOptions) (*ObjectReader, error)
- func (b *BaseDriver) Head(ctx context.Context, key string) (*Object, error)
- func (b *BaseDriver) List(ctx context.Context, opts ListOptions) (*ListResult, error)
- func (b *BaseDriver) ListParts(ctx context.Context, key string, uploadID string) ([]CompletedPart, error)
- func (b *BaseDriver) Name() string
- func (b *BaseDriver) PresignGet(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
- func (b *BaseDriver) PresignPut(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
- func (b *BaseDriver) Put(ctx context.Context, obj *Object, r io.Reader, opts PutOptions) (*Object, error)
- func (b *BaseDriver) ResolveURL(key string) (string, error)
- func (b *BaseDriver) UploadPart(ctx context.Context, key string, uploadID string, partNumber int32, ...) (string, error)
- type Bucket
- func (b *Bucket) AbortMultipart(ctx context.Context, key string, uploadID string) error
- func (b *Bucket) Capabilities() Capability
- func (b *Bucket) Close() error
- func (b *Bucket) CompleteMultipart(ctx context.Context, key string, uploadID string, parts []CompletedPart) (*Object, error)
- func (b *Bucket) Copy(ctx context.Context, srcKey, dstKey string) error
- func (b *Bucket) CreateMultipart(ctx context.Context, key string, opts PutOptions) (uploadID string, err error)
- func (b *Bucket) Delete(ctx context.Context, key string) error
- func (b *Bucket) DeleteBatch(ctx context.Context, keys []string) ([]string, error)
- func (b *Bucket) Driver() Driver
- func (b *Bucket) Exists(ctx context.Context, key string) (bool, error)
- func (b *Bucket) Get(ctx context.Context, key string, opts GetOptions) (*ObjectReader, error)
- func (b *Bucket) GetBytes(ctx context.Context, key string, opts GetOptions) ([]byte, *Object, error)
- func (b *Bucket) Head(ctx context.Context, key string) (*Object, error)
- func (b *Bucket) List(ctx context.Context, opts ListOptions) (*ListResult, error)
- func (b *Bucket) ListParts(ctx context.Context, key string, uploadID string) ([]CompletedPart, error)
- func (b *Bucket) Name() string
- func (b *Bucket) NewWriter(ctx context.Context, key string, opts PutOptions) (*BucketWriter, error)
- func (b *Bucket) OpenSeeker(ctx context.Context, key string) (*SeekableReader, error)
- func (b *Bucket) PresignGet(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
- func (b *Bucket) PresignPut(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
- func (b *Bucket) Put(ctx context.Context, key string, r io.Reader, opts PutOptions) (*Object, error)
- func (b *Bucket) PutBytes(ctx context.Context, key string, data []byte, opts PutOptions) (*Object, error)
- func (b *Bucket) ResolveURL(key string) (string, error)
- func (b *Bucket) UploadPart(ctx context.Context, key string, uploadID string, partNumber int32, ...) (etag string, err error)
- type BucketWriter
- type CDNResolver
- type Cache
- type Capability
- type Client
- func (c *Client) AbortResumableUpload(ctx context.Context, sessionID string) error
- func (c *Client) BatchUpdateMetadata(ctx context.Context, updates map[string]map[string]string) error
- func (c *Client) Bucket(ctx context.Context, providerName string) (*Bucket, error)
- func (c *Client) Close() error
- func (c *Client) Commit(ctx context.Context, objectID string) error
- func (c *Client) CommitResumableUpload(ctx context.Context, sessionID string) (*Object, error)
- func (c *Client) Copy(ctx context.Context, srcTarget string, dstOpts PutOptions) (*Object, error)
- func (c *Client) Delete(ctx context.Context, target string) (err error)
- func (c *Client) DeleteBatch(ctx context.Context, targets []string) (deleted []string, err error)
- func (c *Client) Exists(ctx context.Context, target string) (bool, error)
- func (c *Client) Find(ctx context.Context, filter Filter) ([]Object, error)
- func (c *Client) FindExpiredObjects(ctx context.Context, before time.Time, limit int) ([]Record, error)
- func (c *Client) FindSoftDeletedObjects(ctx context.Context, before time.Time, limit int) ([]Record, error)
- func (c *Client) FindStaleSessions(ctx context.Context, before time.Time, limit int) ([]UploadSession, error)
- func (c *Client) Get(ctx context.Context, target string, opts GetOptions) (reader *ObjectReader, err error)
- func (c *Client) Head(ctx context.Context, target string) (obj *Object, err error)
- func (c *Client) InitiateResumableUpload(ctx context.Context, opts PutOptions, partSize int64, ttl time.Duration) (*UploadSession, error)
- func (c *Client) List(ctx context.Context, opts ListOptions) (*ListResult, error)
- func (c *Client) ListSessionParts(ctx context.Context, sessionID string) ([]CompletedPart, error)
- func (c *Client) Move(ctx context.Context, srcTarget string, dstOpts PutOptions) (*Object, error)
- func (c *Client) OpenSeeker(ctx context.Context, target string) (*SeekableReader, error)
- func (c *Client) PermanentDelete(ctx context.Context, target string) error
- func (c *Client) PermanentDeleteBatch(ctx context.Context, targets []string) ([]string, error)
- func (c *Client) PresignGet(ctx context.Context, target string, opts PresignOptions) (*PresignedURL, error)
- func (c *Client) PresignPut(ctx context.Context, opts PutOptions, presignOpts PresignOptions) (*PresignedURL, *Object, error)
- func (c *Client) Put(ctx context.Context, r io.Reader, opts PutOptions) (savedObj *Object, err error)
- func (c *Client) Reconcile(ctx context.Context, dryRun bool) (*ReconciliationReport, error)
- func (c *Client) Rename(ctx context.Context, target string, newFilename string) error
- func (c *Client) ResolveURL(ctx context.Context, target string) (string, error)
- func (c *Client) Restore(ctx context.Context, target string) error
- func (c *Client) SoftDelete(ctx context.Context, target string) error
- func (c *Client) UpdateMetadata(ctx context.Context, target string, metadata map[string]string) error
- func (c *Client) UploadPart(ctx context.Context, sessionID string, partNumber int, r io.Reader, size int64) (*CompletedPart, error)
- type CompletedPart
- type CustomResolver
- type DelegateDriver
- func (d *DelegateDriver) AbortMultipart(ctx context.Context, key string, uploadID string) error
- func (d *DelegateDriver) Capabilities() Capability
- func (d *DelegateDriver) Close() error
- func (d *DelegateDriver) CompleteMultipart(ctx context.Context, obj *Object, uploadID string, parts []CompletedPart) (*Object, error)
- func (d *DelegateDriver) Copy(ctx context.Context, srcKey, dstKey string) error
- func (d *DelegateDriver) CreateMultipart(ctx context.Context, obj *Object, opts PutOptions) (string, error)
- func (d *DelegateDriver) Delete(ctx context.Context, key string) error
- func (d *DelegateDriver) DeleteBatch(ctx context.Context, keys []string) ([]string, error)
- func (d *DelegateDriver) Get(ctx context.Context, key string, opts GetOptions) (*ObjectReader, error)
- func (d *DelegateDriver) Head(ctx context.Context, key string) (*Object, error)
- func (d *DelegateDriver) List(ctx context.Context, opts ListOptions) (*ListResult, error)
- func (d *DelegateDriver) ListParts(ctx context.Context, key string, uploadID string) ([]CompletedPart, error)
- func (d *DelegateDriver) Name() string
- func (d *DelegateDriver) PresignGet(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
- func (d *DelegateDriver) PresignPut(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
- func (d *DelegateDriver) Put(ctx context.Context, obj *Object, r io.Reader, opts PutOptions) (*Object, error)
- func (d *DelegateDriver) ResolveURL(key string) (string, error)
- func (d *DelegateDriver) UploadPart(ctx context.Context, key string, uploadID string, partNumber int32, ...) (string, error)
- type Driver
- type DriverMiddleware
- type Filter
- type GetOptions
- type LatencyReporter
- type LifecycleState
- type ListOptions
- type ListResult
- type MetadataStore
- type NoopObserver
- func (NoopObserver) OnBytesTransferred(op Operation, bytes int64)
- func (NoopObserver) OnLimiterWait(driver string, waitDuration time.Duration)
- func (NoopObserver) OnOperationEnd(ctx context.Context, op Operation, key string, duration time.Duration, ...)
- func (NoopObserver) OnOperationStart(ctx context.Context, op Operation, key string) context.Context
- type Object
- type ObjectReader
- type Observer
- type Operation
- type Option
- func WithCache(cache Cache) Option
- func WithDefaultVisibility(vis Visibility) Option
- func WithDriver(driver Driver) Option
- func WithKeyGenerator(gen key.Generator) Option
- func WithObserver(obs Observer) Option
- func WithPolicy(p Policy) Option
- func WithRegistry(reg MetadataStore) Option
- func WithRouter(r Router) Option
- func WithURLResolver(resolver URLResolver) Option
- type Policy
- type PresignOptions
- type PresignedURL
- type PutOptions
- type ReconciliationReport
- type Record
- type RouteContext
- type Router
- type S3PathResolver
- type SeekableReader
- type SessionState
- type SizeReader
- type StorageError
- type URLResolver
- type UploadSession
- type ValidationInput
- type Visibility
Constants ¶
const DefaultPresignExpiry = 15 * time.Minute
DefaultPresignExpiry is the default duration for generated presigned URLs.
const MaxKeyLength = 1024
MaxKeyLength defines the maximum permitted byte length for an object key (1024 bytes, conforming to cloud standards).
const SizeUnknown int64 = -1
SizeUnknown represents an unknown or unbounded streaming payload size.
Variables ¶
var ( // ErrObjectNotFound indicates that the requested object does not exist in storage. ErrObjectNotFound = errors.New("blobkit: object not found") // ErrNotFound is an alias for ErrObjectNotFound for ergonomic parity. ErrNotFound = ErrObjectNotFound // ErrBucketNotFound indicates that the target bucket does not exist. ErrBucketNotFound = errors.New("blobkit: bucket not found") // ErrInvalidKey indicates that the provided object key is empty or malformed. ErrInvalidKey = errors.New("blobkit: invalid object key") // ErrInvalidID indicates that the provided object identifier is malformed. ErrInvalidID = errors.New("blobkit: invalid object id") // ErrPreconditionFailed indicates that an ETag or If-Match condition was not met. ErrPreconditionFailed = errors.New("blobkit: precondition failed") ErrProviderUnavailable = errors.New("blobkit: provider unavailable") // ErrQuotaExceeded indicates that the storage account quota or size limit was reached. ErrQuotaExceeded = errors.New("blobkit: storage quota exceeded") // ErrUploadTooLarge indicates that the payload exceeds the provider's maximum single or multipart upload limit. ErrUploadTooLarge = errors.New("blobkit: upload size exceeds maximum allowed") // ErrUnsupportedOperation indicates that the provider does not support the requested operation. ErrUnsupportedOperation = errors.New("blobkit: unsupported operation") // ErrNotSupported is an alias for ErrUnsupportedOperation. ErrNotSupported = ErrUnsupportedOperation // ErrMemoryBudgetExceeded indicates that the global or stream multipart memory budget has been exhausted. ErrMemoryBudgetExceeded = errors.New("blobkit: memory budget exceeded") // ErrNilReader indicates that a nil io.Reader was passed to an upload operation. ErrNilReader = errors.New("blobkit: nil reader provided") // ErrSecurityViolation indicates that an operation violated security policies (e.g. traversal, forbidden extensions). ErrSecurityViolation = errors.New("blobkit: security violation") // ErrMIMEMismatch indicates that the content stream magic bytes contradict the claimed file extension. ErrMIMEMismatch = errors.New("blobkit: MIME type mismatch with content") // ErrInvalidFilename indicates that the provided filename is empty, malformed, or too long. ErrInvalidFilename = errors.New("blobkit: invalid filename") // ErrChecksumMismatch indicates that the computed payload hash does not match the expected checksum. ErrChecksumMismatch = errors.New("blobkit: checksum mismatch") // ErrSizeMismatch indicates that the uploaded byte count differs from the declared size. ErrSizeMismatch = errors.New("blobkit: size mismatch") // ErrObjectLocked indicates that retention policy or active legal hold prohibits modification or deletion. ErrObjectLocked = errors.New("blobkit: object retention locked or legal hold active") // ErrSessionNotFound indicates that the referenced resumable multipart upload session does not exist. ErrSessionNotFound = errors.New("blobkit: upload session not found") // ErrSessionExpired indicates that the resumable multipart upload session has expired. ErrSessionExpired = errors.New("blobkit: upload session expired") // ErrRateLimited indicates that the storage backend rate limit or throttling threshold was exceeded. ErrRateLimited = errors.New("blobkit: rate limit exceeded / throttled") // ErrPermissionDenied indicates that access to the bucket or object was forbidden. ErrPermissionDenied = errors.New("blobkit: permission denied") // ErrInvalidCredentials indicates that authentication credentials were missing, expired, or invalid. ErrInvalidCredentials = errors.New("blobkit: invalid credentials") // ErrMultipartInvalidState indicates an illegal state transition in a multipart upload session. ErrMultipartInvalidState = errors.New("blobkit: multipart invalid state transition") )
var (
// DefaultMaxFilenameLength is the maximum allowed client filename length.
DefaultMaxFilenameLength = 255
)
Functions ¶
func CheckPreconditions ¶
func CheckPreconditions(etag string, modTime time.Time, opts GetOptions) error
CheckPreconditions validates HTTP conditional request headers against object state according to RFC 7232 specifications, returning ErrPreconditionFailed if any condition is unmet.
func EscapeURLPath ¶
EscapeURLPath escapes each segment of a key path with url.PathEscape, preserving '/' path separators.
func FormatError ¶
FormatError returns a sanitized error string.
func IsNotFound ¶
IsNotFound reports whether err represents an object or bucket not found error.
func IsObjectLocked ¶
IsObjectLocked reports whether err represents a retention lock or legal hold block.
func IsPermanent ¶
IsPermanent reports whether err represents a definitive, non-recoverable client error that should not be retried and should not trigger failover circuits.
func IsPermissionDenied ¶
IsPermissionDenied reports whether err represents authentication or authorization failure.
func IsPreconditionFailed ¶
IsPreconditionFailed reports whether err represents a precondition failure.
func IsProviderUnavailable ¶
IsProviderUnavailable reports whether err represents a backend outage or network failure.
func IsQuotaExceeded ¶
IsQuotaExceeded reports whether err represents a storage quota limit error.
func IsRateLimited ¶
IsRateLimited reports whether err represents backend rate limiting or throttling.
func IsSecurityViolation ¶
IsSecurityViolation reports whether err represents a security or validation policy rejection.
func IsTransient ¶
IsTransient reports whether err represents a transient failure eligible for retry or failover. Permanent client errors (such as not found, invalid key, precondition failed, permission denied, checksum mismatch, size mismatch, security violation) are NOT transient.
func PreserveSentinel ¶
PreserveSentinel reports whether err matches a domain sentinel or standard context cancellation error that should be preserved as-is without being wrapped into a generic errors.New().
func ResolvePayload ¶
ResolvePayload inspects the reader and PutOptions to determine exact size semantics. It handles the distinction between known 0-byte objects and unassigned stream sizes.
func SanitizeErrorMessage ¶
SanitizeErrorMessage strips internal proxy dials, local IPs, authorization headers, private keys, and secret tokens from error strings so they are safe for client logging and user-facing error reporting.
func SanitizeFilename ¶
SanitizeFilename removes directory components, null bytes, CRLF characters, and path traversals.
func SanitizeHeader ¶
SanitizeHeader removes CRLF characters and null bytes to prevent HTTP response splitting / header injection.
func ValidateKey ¶
ValidateKey validates an object key against directory traversal, path escape, injection attacks, double/multi-encoding tricks, control characters, and malformed formatting across all operations and storage engines.
Types ¶
type BaseDriver ¶
type BaseDriver struct {
// contains filtered or unexported fields
}
BaseDriver provides a normative, contract-compliant base implementation of Driver. Embed BaseDriver in your custom storage drivers to automatically fulfill all optional capabilities with standardized ErrUnsupportedOperation errors according to the Driver contract.
By embedding BaseDriver, authors of custom storage drivers only need to implement the operations their backend actually supports (e.g. Put, Get, Delete), while guaranteeing that unadvertised capabilities strictly conform to contract requirements.
func NewBaseDriver ¶
func NewBaseDriver(name string, caps Capability) BaseDriver
NewBaseDriver initializes a BaseDriver with a deterministic driver identifier and advertised capabilities.
func (*BaseDriver) AbortMultipart ¶
AbortMultipart is a default stub that returns ErrUnsupportedOperation.
func (*BaseDriver) Capabilities ¶
func (b *BaseDriver) Capabilities() Capability
Capabilities returns the bitmask of features supported by the driver.
func (*BaseDriver) Close ¶
func (b *BaseDriver) Close() error
Close gracefully closes the driver. Default is a no-op returning nil.
func (*BaseDriver) CompleteMultipart ¶
func (b *BaseDriver) CompleteMultipart(ctx context.Context, obj *Object, uploadID string, parts []CompletedPart) (*Object, error)
CompleteMultipart is a default stub that returns ErrUnsupportedOperation.
func (*BaseDriver) Copy ¶
func (b *BaseDriver) Copy(ctx context.Context, srcKey, dstKey string) error
Copy is a default stub that returns ErrUnsupportedOperation.
func (*BaseDriver) CreateMultipart ¶
func (b *BaseDriver) CreateMultipart(ctx context.Context, obj *Object, opts PutOptions) (string, error)
CreateMultipart is a default stub that returns ErrUnsupportedOperation.
func (*BaseDriver) Delete ¶
func (b *BaseDriver) Delete(ctx context.Context, key string) error
Delete is a default stub that returns ErrUnsupportedOperation.
func (*BaseDriver) DeleteBatch ¶
DeleteBatch is a default stub that returns ErrUnsupportedOperation.
func (*BaseDriver) Get ¶
func (b *BaseDriver) Get(ctx context.Context, key string, opts GetOptions) (*ObjectReader, error)
Get is a default stub that returns ErrUnsupportedOperation.
func (*BaseDriver) List ¶
func (b *BaseDriver) List(ctx context.Context, opts ListOptions) (*ListResult, error)
List is a default stub that returns ErrUnsupportedOperation.
func (*BaseDriver) ListParts ¶
func (b *BaseDriver) ListParts(ctx context.Context, key string, uploadID string) ([]CompletedPart, error)
ListParts is a default stub that returns ErrUnsupportedOperation.
func (*BaseDriver) PresignGet ¶
func (b *BaseDriver) PresignGet(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
PresignGet is a default stub that returns ErrUnsupportedOperation.
func (*BaseDriver) PresignPut ¶
func (b *BaseDriver) PresignPut(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
PresignPut is a default stub that returns ErrUnsupportedOperation.
func (*BaseDriver) Put ¶
func (b *BaseDriver) Put(ctx context.Context, obj *Object, r io.Reader, opts PutOptions) (*Object, error)
Put is a default stub that returns ErrUnsupportedOperation.
func (*BaseDriver) ResolveURL ¶
func (b *BaseDriver) ResolveURL(key string) (string, error)
ResolveURL is a default stub that returns ErrUnsupportedOperation.
type Bucket ¶
type Bucket struct {
// contains filtered or unexported fields
}
Bucket provides a lightweight, stateless, key-value object storage abstraction. It bypasses the database metadata registry, canonical ObjectID translations, and background lifecycle management of Client, communicating directly with a Driver using raw storage keys (e.g. "avatars/user-123.png").
Use Bucket when your application needs high-throughput, direct wire-level object storage without database dependencies or opinionated key generation.
func (*Bucket) AbortMultipart ¶
AbortMultipart cancels a multi-part upload session and cleans up staged parts.
func (*Bucket) Capabilities ¶
func (b *Bucket) Capabilities() Capability
Capabilities returns the supported capability bitmask of the driver.
func (*Bucket) CompleteMultipart ¶
func (b *Bucket) CompleteMultipart(ctx context.Context, key string, uploadID string, parts []CompletedPart) (*Object, error)
CompleteMultipart finalizes an ongoing multi-part upload session.
func (*Bucket) CreateMultipart ¶
func (b *Bucket) CreateMultipart(ctx context.Context, key string, opts PutOptions) (uploadID string, err error)
CreateMultipart initializes a multi-part upload session directly on the storage provider.
func (*Bucket) DeleteBatch ¶
DeleteBatch removes multiple keys in a single operation.
func (*Bucket) Get ¶
func (b *Bucket) Get(ctx context.Context, key string, opts GetOptions) (*ObjectReader, error)
Get retrieves an object stream and its metadata.
func (*Bucket) GetBytes ¶
func (b *Bucket) GetBytes(ctx context.Context, key string, opts GetOptions) ([]byte, *Object, error)
GetBytes reads the entire object payload into an in-memory byte slice.
func (*Bucket) List ¶
func (b *Bucket) List(ctx context.Context, opts ListOptions) (*ListResult, error)
List queries objects matching prefix and filter criteria.
func (*Bucket) ListParts ¶
func (b *Bucket) ListParts(ctx context.Context, key string, uploadID string) ([]CompletedPart, error)
ListParts returns the list of parts already committed to an active multipart session.
func (*Bucket) NewWriter ¶
func (b *Bucket) NewWriter(ctx context.Context, key string, opts PutOptions) (*BucketWriter, error)
NewWriter creates an io.WriteCloser that streams data directly to the given key. The upload executes concurrently as bytes are written. Calling Close() finalizes the upload.
func (*Bucket) OpenSeeker ¶
OpenSeeker creates an io.ReadSeekCloser and io.ReaderAt over the given object key. It verifies the driver's CapByteRangeGet capability and fetches the object's total size via Head.
func (*Bucket) PresignGet ¶
func (b *Bucket) PresignGet(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
PresignGet generates a temporary signed download URL for direct client access.
func (*Bucket) PresignPut ¶
func (b *Bucket) PresignPut(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
PresignPut generates a temporary signed upload URL for direct browser-to-storage uploads.
func (*Bucket) Put ¶
func (b *Bucket) Put(ctx context.Context, key string, r io.Reader, opts PutOptions) (*Object, error)
Put uploads an object stream directly to the specified key.
func (*Bucket) PutBytes ¶
func (b *Bucket) PutBytes(ctx context.Context, key string, data []byte, opts PutOptions) (*Object, error)
PutBytes is a convenience method to store an in-memory byte slice directly.
func (*Bucket) ResolveURL ¶
ResolveURL builds a public access or CDN delivery URL for the given key.
type BucketWriter ¶
type BucketWriter struct {
// contains filtered or unexported fields
}
BucketWriter implements io.WriteCloser for streaming writes directly into storage.
func (*BucketWriter) Close ¶
func (w *BucketWriter) Close() error
Close finalizes the upload stream and waits for the storage backend to confirm persistence.
func (*BucketWriter) CloseWithError ¶
func (w *BucketWriter) CloseWithError(err error) error
CloseWithError aborts the streaming upload with the specified error.
type CDNResolver ¶
type CDNResolver struct {
// contains filtered or unexported fields
}
CDNResolver resolves object keys against a base CDN or public domain URL (e.g. "https://cdn.example.com").
func NewCDNResolver ¶
func NewCDNResolver(baseURL string) *CDNResolver
NewCDNResolver initializes a CDNResolver. Trailing slashes are stripped from baseURL.
func (*CDNResolver) ResolveURL ¶
func (c *CDNResolver) ResolveURL(key string) string
ResolveURL appends the sanitized key to the configured base URL.
type Cache ¶
type Cache interface {
// Get retrieves cached metadata for the given storage key or object ID.
Get(key string) (*Object, bool)
// Set caches object metadata with a specific TTL.
Set(key string, obj *Object, ttl time.Duration)
// SetNegative records a negative cache entry (not found) to shield storage backends.
SetNegative(key string, ttl time.Duration)
// IsNegative checks whether a key is currently negative-cached.
IsNegative(key string) bool
// Delete invalidates any cached entries for the specified key.
Delete(key string)
// Purge clears all entries in the cache.
Purge()
}
Cache defines an optional cache interface for storing object metadata and negative lookups.
type Capability ¶
type Capability uint32
Capability is a bitmask representing features supported by a storage driver.
const ( // CapDirectPut indicates support for single-shot uploads. CapDirectPut Capability = 1 << iota // CapMultipartPut indicates support for internal chunked multipart uploads. CapMultipartPut // CapPresignGet indicates support for generating presigned GET URLs. CapPresignGet // CapPresignPut indicates support for generating presigned PUT URLs. CapPresignPut // CapBatchDelete indicates support for deleting multiple keys in a single operation. CapBatchDelete // CapByteRangeGet indicates support for HTTP Range requests. CapByteRangeGet // CapCopy indicates support for server-side object duplication. CapCopy // CapMultipartSession indicates support for resumable multi-part upload primitives. CapMultipartSession )
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is the high-level object storage infrastructure orchestrator. It sits between application logic and physical storage drivers, managing identity, key generation, streaming I/O, routing, metadata, and access delivery.
func (*Client) AbortResumableUpload ¶
AbortResumableUpload aborts an in-progress multipart session and purges partial chunks.
func (*Client) BatchUpdateMetadata ¶
func (c *Client) BatchUpdateMetadata(ctx context.Context, updates map[string]map[string]string) error
BatchUpdateMetadata applies metadata key-value updates across multiple objects in the registry.
func (*Client) Bucket ¶
Bucket returns a low-level Bucket bound to the specified provider name, or the default driver resolved by the router if providerName is empty.
func (*Client) Close ¶
Close gracefully releases any connections across all registered drivers and the registry.
func (*Client) Commit ¶
Commit verifies that an uploaded blob exists in storage and transitions its status from StatePending to StateCommitted in the database registry.
func (*Client) CommitResumableUpload ¶
CommitResumableUpload finalizes an active resumable upload session, assembling all parts into a completed object in storage and transitioning its registry record to StateCommitted.
func (*Client) Copy ¶
Copy duplicates an object to a new logical destination. If the source and destination drivers are identical and support CapCopy, a fast server-side copy is executed; otherwise, data is streamed between drivers.
func (*Client) Delete ¶
Delete removes an object from storage and marks or deletes it in the registry.
func (*Client) DeleteBatch ¶
DeleteBatch removes multiple objects in a single batch operation across their respective storage providers.
func (*Client) Exists ¶
Exists reports whether an object exists in storage without downloading its body.
func (*Client) Find ¶
Find queries objects by metadata attributes (namespace, owner_id, status, mime, etc.) from the database registry without requiring knowledge of storage keys or URLs.
func (*Client) FindExpiredObjects ¶
func (c *Client) FindExpiredObjects(ctx context.Context, before time.Time, limit int) ([]Record, error)
FindExpiredObjects returns records whose scheduled expiration has elapsed.
func (*Client) FindSoftDeletedObjects ¶
func (c *Client) FindSoftDeletedObjects(ctx context.Context, before time.Time, limit int) ([]Record, error)
FindSoftDeletedObjects returns records marked as soft-deleted before the specified cutoff.
func (*Client) FindStaleSessions ¶
func (c *Client) FindStaleSessions(ctx context.Context, before time.Time, limit int) ([]UploadSession, error)
FindStaleSessions returns active sessions that have passed their expiration timestamp.
func (*Client) Get ¶
func (c *Client) Get(ctx context.Context, target string, opts GetOptions) (reader *ObjectReader, err error)
Get retrieves an object stream. Target can be either a canonical logical ObjectID (when registry is enabled) or a physical storage key.
func (*Client) InitiateResumableUpload ¶
func (c *Client) InitiateResumableUpload(ctx context.Context, opts PutOptions, partSize int64, ttl time.Duration) (*UploadSession, error)
InitiateResumableUpload initializes a multipart upload session for large files or unstable networks. It assigns an ObjectID, physical storage key, creates a multipart session on the storage driver, and returns an UploadSession handle.
func (*Client) List ¶
func (c *Client) List(ctx context.Context, opts ListOptions) (*ListResult, error)
List lists objects directly from the storage driver.
func (*Client) ListSessionParts ¶
ListSessionParts retrieves all completed parts for the given upload session.
func (*Client) Move ¶
Move is a best-effort copy and delete. It is not an atomic rename operation. If the server-side copy succeeds but the deletion fails, the object will exist at both locations.
func (*Client) OpenSeeker ¶
OpenSeeker returns an io.ReadSeekCloser and io.ReaderAt over the specified target (ObjectID or Key).
func (*Client) PermanentDelete ¶
PermanentDelete physically destroys an object from the storage backend and purges its metadata.
func (*Client) PermanentDeleteBatch ¶
PermanentDeleteBatch removes multiple objects in bulk by grouping them by provider and invoking Driver.DeleteBatch, with automatic metadata cleanup and cache eviction.
func (*Client) PresignGet ¶
func (c *Client) PresignGet(ctx context.Context, target string, opts PresignOptions) (*PresignedURL, error)
PresignGet generates a time-limited signed URL for authorized download. Target can be an ObjectID or a physical storage key.
func (*Client) PresignPut ¶
func (c *Client) PresignPut(ctx context.Context, opts PutOptions, presignOpts PresignOptions) (*PresignedURL, *Object, error)
PresignPut generates a time-limited signed URL for direct client upload. It assigns an ObjectID, calculates the physical storage key, and registers a pending record.
func (*Client) Put ¶
func (c *Client) Put(ctx context.Context, r io.Reader, opts PutOptions) (savedObj *Object, err error)
Put uploads an object stream based on the caller's semantic intent. It assigns a canonical logical ObjectID, generates a physical storage key, peeks MIME types without buffering entire files, and commits metadata to the registry if enabled.
func (*Client) Reconcile ¶
Reconcile audits and synchronizes database registry state with physical storage backends. It detects orphan files (present in driver but absent from registry) and ghost records (marked committed in registry but missing in physical storage). If dryRun is false, ghost records are marked as StateDeleted.
func (*Client) Rename ¶
Rename updates the logical client-facing filename without moving or re-uploading physical bytes.
func (*Client) ResolveURL ¶
ResolveURL generates a public CDN or base delivery URL on demand. Target can be an ObjectID or a physical storage key.
func (*Client) Restore ¶
Restore recovers a soft-deleted object, returning its lifecycle state to StateCommitted.
func (*Client) SoftDelete ¶
SoftDelete marks an object as deleted in the registry, hiding it from standard Get/Head queries without immediately destroying the underlying physical storage blob.
type CompletedPart ¶
type CompletedPart struct {
// PartNumber is the 1-based index of the part.
PartNumber int32 `json:"part_number"`
// ETag is the entity tag assigned by the storage provider for this part.
ETag string `json:"etag"`
// Size is the part size in bytes.
Size int64 `json:"size"`
}
CompletedPart records information about an uploaded multipart part.
type CustomResolver ¶
CustomResolver adapts an arbitrary formatting function into a URLResolver.
func (CustomResolver) ResolveURL ¶
func (f CustomResolver) ResolveURL(key string) string
ResolveURL invokes the underlying custom function.
type DelegateDriver ¶
type DelegateDriver struct {
Driver Driver
}
DelegateDriver is a transparent proxy struct that implements Driver by forwarding all calls to its inner Driver. Custom middleware authors should embed DelegateDriver and selectively override only the specific methods they wish to intercept.
func NewDelegateDriver ¶
func NewDelegateDriver(target Driver) DelegateDriver
NewDelegateDriver creates a DelegateDriver wrapping the specified target Driver.
func (*DelegateDriver) AbortMultipart ¶
AbortMultipart delegates to the inner driver.
func (*DelegateDriver) Capabilities ¶
func (d *DelegateDriver) Capabilities() Capability
Capabilities delegates to the inner driver.
func (*DelegateDriver) Close ¶
func (d *DelegateDriver) Close() error
Close delegates to the inner driver.
func (*DelegateDriver) CompleteMultipart ¶
func (d *DelegateDriver) CompleteMultipart(ctx context.Context, obj *Object, uploadID string, parts []CompletedPart) (*Object, error)
CompleteMultipart delegates to the inner driver.
func (*DelegateDriver) Copy ¶
func (d *DelegateDriver) Copy(ctx context.Context, srcKey, dstKey string) error
Copy delegates to the inner driver.
func (*DelegateDriver) CreateMultipart ¶
func (d *DelegateDriver) CreateMultipart(ctx context.Context, obj *Object, opts PutOptions) (string, error)
CreateMultipart delegates to the inner driver.
func (*DelegateDriver) Delete ¶
func (d *DelegateDriver) Delete(ctx context.Context, key string) error
Delete delegates to the inner driver.
func (*DelegateDriver) DeleteBatch ¶
DeleteBatch delegates to the inner driver.
func (*DelegateDriver) Get ¶
func (d *DelegateDriver) Get(ctx context.Context, key string, opts GetOptions) (*ObjectReader, error)
Get delegates to the inner driver.
func (*DelegateDriver) List ¶
func (d *DelegateDriver) List(ctx context.Context, opts ListOptions) (*ListResult, error)
List delegates to the inner driver.
func (*DelegateDriver) ListParts ¶
func (d *DelegateDriver) ListParts(ctx context.Context, key string, uploadID string) ([]CompletedPart, error)
ListParts delegates to the inner driver.
func (*DelegateDriver) Name ¶
func (d *DelegateDriver) Name() string
Name delegates to the inner driver.
func (*DelegateDriver) PresignGet ¶
func (d *DelegateDriver) PresignGet(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
PresignGet delegates to the inner driver.
func (*DelegateDriver) PresignPut ¶
func (d *DelegateDriver) PresignPut(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
PresignPut delegates to the inner driver.
func (*DelegateDriver) Put ¶
func (d *DelegateDriver) Put(ctx context.Context, obj *Object, r io.Reader, opts PutOptions) (*Object, error)
Put delegates to the inner driver.
func (*DelegateDriver) ResolveURL ¶
func (d *DelegateDriver) ResolveURL(key string) (string, error)
ResolveURL delegates to the inner driver.
type Driver ¶
type Driver interface {
// Name returns the driver identifier (e.g. "r2-primary", "s3-backup", "memory").
// MUST return a non-empty, deterministic string identifying this driver instance.
Name() string
// Capabilities returns the bitmask of operations supported by this driver.
// MUST accurately declare supported features. A driver MUST NOT declare a capability
// it cannot fulfill according to the normative contract.
Capabilities() Capability
// Put uploads an object stream to the driver backend.
//
// Semantic Guarantees:
// - Inputs: obj MUST be non-nil with a valid Key. r MUST be non-nil.
// - Missing/Invalid inputs: If r is nil, MUST return ErrNilReader. If obj is nil or Key is invalid, MUST return ErrInvalidKey or ErrSecurityViolation.
// - Size semantics: If opts.ExplicitSize is true or opts.Size >= 0, the stream MUST yield exactly opts.Size bytes.
// If fewer bytes are read, MUST fail with ErrSizeMismatch.
// If surplus bytes remain after reading opts.Size bytes, MUST fail with ErrSizeMismatch.
// On ErrSizeMismatch or failure, the driver MUST NOT leave partially-created or corrupted objects in storage.
// - Empty objects: MUST support storing, overwriting, and retrieving valid 0-byte objects.
// - Overwrites: If an object already exists at obj.Key, Put MUST overwrite it.
// Filesystem implementations MUST perform atomic replacement (e.g. via temporary file rename).
// - Context & Cancellation: If ctx is canceled or times out before or during upload, MUST abort and return ctx.Err().
// MUST clean up partial objects on cancellation.
// - Concurrency: Put MUST be safe for concurrent execution across identical or distinct keys.
Put(ctx context.Context, obj *Object, r io.Reader, opts PutOptions) (*Object, error)
// Get retrieves an object stream and its metadata.
//
// Semantic Guarantees:
// - Inputs: key MUST be valid. If key is invalid, MUST return ErrInvalidKey or ErrSecurityViolation.
// - Missing object: If the object does not exist, MUST return ErrObjectNotFound.
// - Empty object: If the object is 0 bytes, MUST return an ObjectReader whose Body yields 0 bytes and io.EOF.
// - Preconditions: If opts contains IfMatch, IfNoneMatch, IfModifiedSince, or IfUnmodifiedSince,
// the driver MUST evaluate them. If preconditions fail, MUST return ErrPreconditionFailed.
// - Byte-Range: If opts.Range is set and CapByteRangeGet is supported, MUST return the requested subslice.
// - Context & Cancellation: If ctx is canceled, reading or requesting MUST return ctx.Err().
Get(ctx context.Context, key string, opts GetOptions) (*ObjectReader, error)
// Head inspects an object and returns its metadata without fetching the body.
//
// Semantic Guarantees:
// - Inputs: key MUST be valid. If invalid, MUST return ErrInvalidKey or ErrSecurityViolation.
// - Missing object: If the object does not exist, MUST return ErrObjectNotFound.
// - Empty object: If the object is 0 bytes, MUST return Object with Size == 0 and nil error.
// - Content: MUST NOT read or consume the body payload.
Head(ctx context.Context, key string) (*Object, error)
// Delete removes an object from storage.
//
// Semantic Guarantees:
// - Inputs: key MUST be valid. If invalid, MUST return ErrInvalidKey or ErrSecurityViolation.
// - Idempotency: Deleting an already-deleted or non-existent key MUST succeed and return nil error.
// - Overwrite & Concurrency: MUST be safe for concurrent execution.
// - Context: If ctx is canceled before execution, MUST return ctx.Err().
Delete(ctx context.Context, key string) error
// DeleteBatch removes multiple keys in a batch, returning deleted keys.
//
// Semantic Guarantees:
// - CapBatchDelete: Only invoked if driver declares CapBatchDelete.
// - Empty input: If keys is empty, MUST return empty list and nil error.
// - Partial failure: MUST return the list of successfully deleted keys alongside any error encountered.
DeleteBatch(ctx context.Context, keys []string) ([]string, error)
// Copy duplicates an object within this driver backend.
//
// Semantic Guarantees:
// - CapCopy: Only invoked if driver declares CapCopy.
// - Missing source: If srcKey does not exist, MUST return ErrObjectNotFound.
// - Destination: Overwrites dstKey if it exists. Source object MUST remain unchanged.
Copy(ctx context.Context, srcKey, dstKey string) error
// List queries objects matching criteria.
//
// Semantic Guarantees:
// - Prefix & Delimiter: MUST accurately filter by prefix and group common prefixes when delimiter is provided.
List(ctx context.Context, opts ListOptions) (*ListResult, error)
// PresignGet creates a temporary signed URL for object download.
// CapPresignGet: Only invoked if driver declares CapPresignGet.
PresignGet(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
// PresignPut creates a temporary signed URL for direct object upload.
// CapPresignPut: Only invoked if driver declares CapPresignPut.
PresignPut(ctx context.Context, key string, opts PresignOptions) (*PresignedURL, error)
// ResolveURL builds a public access or CDN URL for the given key.
ResolveURL(key string) (string, error)
// CreateMultipart initiates a resumable multi-part upload session on the backend.
//
// Semantic Guarantees:
// - CapMultipartSession: Only invoked if driver declares CapMultipartSession.
// - Inputs: obj MUST be non-nil with valid Key.
// - State: Initializes session in StateCreated. Returns unique uploadID.
CreateMultipart(ctx context.Context, obj *Object, opts PutOptions) (uploadID string, err error)
// UploadPart uploads a single chunk of a multipart upload.
//
// Semantic Guarantees:
// - Inputs: partNumber MUST be >= 1. size MUST match the exact payload read from r.
// - Size verification: If r yields fewer or more bytes than size, MUST fail with ErrSizeMismatch.
// - Session existence: If uploadID does not exist or has been completed/aborted, MUST return ErrSessionNotFound.
UploadPart(ctx context.Context, key string, uploadID string, partNumber int32, r io.Reader, size int64) (etag string, err error)
// CompleteMultipart finalizes a multipart upload session.
//
// Semantic Guarantees:
// - Inputs: parts MUST contain at least one part (unless backend allows 0-part empty).
// - Parts validation: parts MUST be ordered or sortable by partNumber without missing or duplicate parts.
// - State: Transitions session to StateCompleted. Subsequent operations on uploadID MUST fail with ErrSessionNotFound.
// - Cleanup: MUST clean up temporary staged chunks.
CompleteMultipart(ctx context.Context, obj *Object, uploadID string, parts []CompletedPart) (*Object, error)
// AbortMultipart cancels a multipart upload and cleans up stored parts.
//
// Semantic Guarantees:
// - State: Transitions session to StateAborted. Cleans up all staged chunks.
// - Idempotency: Calling AbortMultipart on an already-aborted session SHOULD return nil error or ErrSessionNotFound.
AbortMultipart(ctx context.Context, key string, uploadID string) error
// ListParts returns the list of parts already uploaded for an active session.
//
// Semantic Guarantees:
// - If uploadID does not exist or is aborted/completed, MUST return ErrSessionNotFound.
ListParts(ctx context.Context, key string, uploadID string) ([]CompletedPart, error)
// Close gracefully terminates open connections and worker pools.
Close() error
}
Driver is the storage abstraction interface implemented by backend drivers (e.g. AWS S3, Cloudflare R2, MinIO, Wasabi, In-Memory, POSIX FS, SFTP, WebDAV, GCS, Azure, Google Drive).
Driver Contract (Normative Specification): All Driver implementations MUST conform strictly to the semantic guarantees defined here. Implementations MUST NOT redefine or weaken these guarantees based on backend quirks.
func WrapDriver ¶
func WrapDriver(driver Driver, middlewares ...DriverMiddleware) Driver
WrapDriver decorates a target Driver with one or more DriverMiddlewares. Middlewares are executed in the order they are passed: the first middleware in the list is the outermost wrapper, executing first before passing control inward.
type DriverMiddleware ¶
DriverMiddleware wraps an existing Driver with interceptor logic. It allows modifying requests, injecting behaviors (such as encryption, compression, rate limiting, or metrics), or intercepting responses at the wire level.
func LatencyMiddleware ¶
func LatencyMiddleware(reporter LatencyReporter) DriverMiddleware
LatencyMiddleware creates a DriverMiddleware that measures and reports the wire-level execution duration of storage driver operations.
type Filter ¶
type Filter struct {
// ObjectID filters by canonical identifier.
ObjectID string
// Key filters by physical storage key.
Key string
// Namespace filters by category or sub-category (e.g. "bots/autorespon").
Namespace string
// OwnerID filters by owner, user, or tenant.
OwnerID string
// MIMEType filters by MIME type (e.g. "image/png").
MIMEType string
// OriginalFilename filters by user-facing filename.
OriginalFilename string
// Status filters by lifecycle state (pending, committed, deleted).
Status LifecycleState
// Provider filters by storage driver name.
Provider string
// CreatedAfter filters records created on or after this timestamp.
CreatedAfter *time.Time
// CreatedBefore filters records created on or before this timestamp.
CreatedBefore *time.Time
// DeletedBefore filters records deleted on or before this timestamp.
DeletedBefore *time.Time
// Metadata requires matching key-value pairs.
Metadata map[string]string
// Limit bounds the result count (default 100, max 1000).
Limit int
// Offset enables pagination skipping.
Offset int
}
Filter specifies query criteria for discovering objects by metadata without needing URLs.
type GetOptions ¶
type GetOptions struct {
// Range specifies an HTTP byte range (e.g. "bytes=0-1024").
Range string
// IfMatch returns the object only if its ETag matches this value.
IfMatch string
// IfNoneMatch returns the object only if its ETag does not match this value.
IfNoneMatch string
// IfModifiedSince returns the object only if it has been modified since this timestamp.
IfModifiedSince *time.Time
// IfUnmodifiedSince returns the object only if it has not been modified since this timestamp.
IfUnmodifiedSince *time.Time
}
GetOptions configures an object download or stream retrieval.
type LatencyReporter ¶
LatencyReporter is a callback invoked after every wire operation with exact execution duration.
type LifecycleState ¶
type LifecycleState string
LifecycleState defines the storage lifecycle status of an object.
const ( // StatePending indicates that the upload is initiated or pending validation. StatePending LifecycleState = "pending" // StateCommitted indicates that the upload is finalized and verified in storage. StateCommitted LifecycleState = "committed" // StateAborted indicates that the upload failed or was aborted before commit. StateAborted LifecycleState = "aborted" // StateDeleted indicates that the object has been soft-deleted or scheduled for purge. StateDeleted LifecycleState = "deleted" )
type ListOptions ¶
type ListOptions struct {
// Prefix filters objects starting with this prefix string.
Prefix string
// Delimiter causes keys containing this delimiter to be grouped in CommonPrefixes.
Delimiter string
// Cursor is the continuation token for pagination.
Cursor string
// Limit specifies the maximum number of items to return.
Limit int
}
ListOptions specifies parameters for listing objects in a bucket or prefix.
type ListResult ¶
type ListResult struct {
// Objects is the list of objects returned.
Objects []Object `json:"objects"`
// NextCursor is the continuation token to pass to subsequent List calls, or empty if done.
NextCursor string `json:"next_cursor,omitempty"`
// CommonPrefixes contains prefixes grouped by the delimiter (e.g. directories).
CommonPrefixes []string `json:"common_prefixes,omitempty"`
// IsTruncated indicates whether more items remain in the bucket.
IsTruncated bool `json:"is_truncated"`
}
ListResult holds the outcome of a List operation.
type MetadataStore ¶
type MetadataStore interface {
// Save creates or updates an object record in the registry.
Save(ctx context.Context, record *Record) error
// GetByID retrieves a record by its logical ObjectID.
GetByID(ctx context.Context, objectID string) (*Record, error)
// GetByKey retrieves a record by its physical storage key.
GetByKey(ctx context.Context, key string) (*Record, error)
// Find queries records matching filter criteria.
Find(ctx context.Context, filter Filter) ([]Record, error)
// UpdateStatus transitions an object lifecycle state (e.g. pending -> committed, or soft deleted).
UpdateStatus(ctx context.Context, objectID string, status LifecycleState) error
// UpdateMetadata replaces or updates the user-defined metadata map for an object.
UpdateMetadata(ctx context.Context, objectID string, metadata map[string]string) error
// UpdateFilename updates the client-facing filename of an object without moving physical bytes.
UpdateFilename(ctx context.Context, objectID string, newFilename string) error
// Delete marks an object as soft-deleted or removes it.
Delete(ctx context.Context, objectID string) error
// HardDelete permanently purges the record from the database registry.
HardDelete(ctx context.Context, objectID string) error
// FindExpired returns committed objects whose ExpiresAt is on or before the given timestamp.
FindExpired(ctx context.Context, before time.Time, limit int) ([]Record, error)
// SaveSession persists or updates a resumable multipart upload session.
SaveSession(ctx context.Context, session *UploadSession) error
// GetSession retrieves an active upload session by ID.
GetSession(ctx context.Context, sessionID string) (*UploadSession, error)
// DeleteSession removes a session upon completion or abort.
DeleteSession(ctx context.Context, sessionID string) error
// FindStaleSessions returns active sessions whose ExpiresAt is on or before the given timestamp.
FindStaleSessions(ctx context.Context, before time.Time, limit int) ([]UploadSession, error)
// Close gracefully closes any open database pool connections.
Close() error
}
MetadataStore defines the database metadata repository interface. When enabled, it acts as the source of truth for metadata and indexing.
type NoopObserver ¶
type NoopObserver struct{}
NoopObserver is a zero-cost inert observer implementation used when no telemetry is attached.
func (NoopObserver) OnBytesTransferred ¶
func (NoopObserver) OnBytesTransferred(op Operation, bytes int64)
func (NoopObserver) OnLimiterWait ¶
func (NoopObserver) OnLimiterWait(driver string, waitDuration time.Duration)
func (NoopObserver) OnOperationEnd ¶
func (NoopObserver) OnOperationStart ¶
type Object ¶
type Object struct {
// ID is the logical identifier (typically UUIDv7) used for database indexing and reference.
ID string `json:"id"`
// Namespace partitions objects logically (e.g. "avatars", "bots/autorespon", "media").
Namespace string `json:"namespace"`
// OwnerID identifies the tenant, user, or entity owning this object.
OwnerID string `json:"owner_id,omitempty"`
// Key is the physical storage path within the provider's bucket.
Key string `json:"key"`
// Bucket is the name of the bucket where the object resides.
Bucket string `json:"bucket"`
// Size is the object content length in bytes.
Size int64 `json:"size"`
// ContentType is the detected or explicitly specified MIME type.
ContentType string `json:"content_type"`
// ETag is the entity tag assigned by the storage provider.
ETag string `json:"etag,omitempty"`
// ChecksumSHA256 is the hex-encoded SHA-256 hash of the object payload (if computed).
ChecksumSHA256 string `json:"checksum_sha256,omitempty"`
// OriginalFilename is the client-facing filename (e.g. "photo.jpg").
OriginalFilename string `json:"original_filename,omitempty"`
// Visibility determines whether the object is public or private.
Visibility Visibility `json:"visibility"`
// Status indicates the current lifecycle state (pending, committed, deleted).
Status LifecycleState `json:"status"`
// Metadata contains user-defined metadata key-value pairs.
Metadata map[string]string `json:"metadata,omitempty"`
// RetentionUntil specifies when retention expires. The object cannot be deleted before this date.
RetentionUntil *time.Time `json:"retention_until,omitempty"`
// ExpiresAt specifies when the object expires and is eligible for garbage collection.
ExpiresAt *time.Time `json:"expires_at,omitempty"`
// LegalHold prevents deletion or modification when true, regardless of retention expiration.
LegalHold bool `json:"legal_hold,omitempty"`
// DeletedAt records when the object was soft-deleted.
DeletedAt *time.Time `json:"deleted_at,omitempty"`
// ClientChecksum is the optional client-declared payload checksum.
ClientChecksum string `json:"client_checksum,omitempty"`
// CreatedAt is the logical creation timestamp.
CreatedAt time.Time `json:"created_at"`
// UpdatedAt is the last modification timestamp.
UpdatedAt time.Time `json:"updated_at"`
// Provider is the identifier of the driver that stored this object (e.g. "r2-primary", "s3-backup").
Provider string `json:"provider"`
}
Object represents a stored blob and its canonical system and custom metadata.
type ObjectReader ¶
type ObjectReader struct {
Object
Body io.ReadCloser
}
ObjectReader pairs object metadata with an active streaming body. Callers must call Close() when finished reading.
func (*ObjectReader) Close ¶
func (r *ObjectReader) Close() error
Close closes the underlying reader stream.
func (*ObjectReader) Read ¶
func (r *ObjectReader) Read(p []byte) (n int, err error)
Read implements io.Reader by delegating to the underlying body stream.
func (*ObjectReader) WriteTo ¶
func (r *ObjectReader) WriteTo(w io.Writer) (int64, error)
WriteTo implements io.WriterTo by forwarding the stream directly to w. If the underlying Body implements io.WriterTo (such as *os.File), it enables zero-copy kernel transfer mechanisms (e.g. Linux sendfile(2) / splice(2)) in standard HTTP handlers.
type Observer ¶
type Observer interface {
// OnOperationStart is invoked at the beginning of an object storage operation.
// It may enrich and return a child context (e.g. for distributed tracing spans).
OnOperationStart(ctx context.Context, op Operation, key string) context.Context
// OnOperationEnd is invoked when an operation finishes, reporting duration and error status.
OnOperationEnd(ctx context.Context, op Operation, key string, duration time.Duration, err error)
// OnBytesTransferred records data transfer volume for streaming uploads and downloads.
OnBytesTransferred(op Operation, bytes int64)
// OnLimiterWait records backpressure delay caused by concurrency rate limiters.
OnLimiterWait(driver string, waitDuration time.Duration)
}
Observer provides vendor-neutral instrumentation hooks for telemetry, metrics collection, distributed tracing, and audit logging.
type Operation ¶
type Operation string
Operation represents the high-level storage action being performed.
const ( OpPut Operation = "put" OpGet Operation = "get" OpHead Operation = "head" OpDelete Operation = "delete" OpList Operation = "list" OpPresignGet Operation = "presign_get" OpPresignPut Operation = "presign_put" OpCopy Operation = "copy" OpMove Operation = "move" OpUploadPart Operation = "upload_part" OpMultipart Operation = "multipart" OpSoftDelete Operation = "soft_delete" OpRestore Operation = "restore" OpPermanentDelete Operation = "permanent_delete" )
type Option ¶
type Option func(*Client)
Option represents a functional configuration option for the BlobKit Client.
func WithCache ¶
WithCache sets an optional caching layer for object metadata and negative lookups.
func WithDefaultVisibility ¶
func WithDefaultVisibility(vis Visibility) Option
WithDefaultVisibility sets the default visibility for uploaded objects.
func WithDriver ¶
WithDriver sets a single fixed storage driver for the client.
func WithKeyGenerator ¶
WithKeyGenerator configures the physical key naming strategy.
func WithObserver ¶
WithObserver sets a vendor-neutral observability instrumentation hook.
func WithPolicy ¶
WithPolicy sets the default upload security and validation policy for the client.
func WithRegistry ¶
func WithRegistry(reg MetadataStore) Option
WithRegistry attaches an optional database metadata registry.
func WithRouter ¶
WithRouter sets a custom routing policy (failover, namespace, etc.).
func WithURLResolver ¶
func WithURLResolver(resolver URLResolver) Option
WithURLResolver configures the public delivery URL resolver.
type Policy ¶
type Policy struct {
// AllowedMIMEs is a whitelist of permitted MIME types (e.g. ["image/jpeg", "image/*", "audio/*"]).
AllowedMIMEs []string
// DeniedMIMEs is a blacklist of forbidden MIME types (e.g. ["application/x-dosexec", "application/x-sh"]).
DeniedMIMEs []string
// AllowedExtensions is a whitelist of permitted file extensions (e.g. [".jpg", ".png", ".pdf"]).
AllowedExtensions []string
// DeniedExtensions is a blacklist of forbidden extensions (e.g. [".exe", ".sh", ".bat", ".cmd", ".php"]).
DeniedExtensions []string
// MaxObjectSize is the maximum allowed payload size in bytes (0 means unlimited).
MaxObjectSize int64
// MinObjectSize is the minimum required payload size in bytes (0 means no minimum).
MinObjectSize int64
// MaxFilenameLength is the maximum allowed filename length (defaults to 255).
MaxFilenameLength int
// DisallowMIMEMismatch flags whether an obvious mismatch between file extension and detected MIME is forbidden.
DisallowMIMEMismatch bool
// ContentScanner is an optional custom scanner hook (e.g. antivirus or deep payload inspection).
// It MUST return an io.Reader that allows subsequent operations to read the full payload,
// either by returning the original reader unconsumed, or by returning a new reader that buffers/replays the consumed bytes.
ContentScanner func(ctx context.Context, r io.Reader, filename, mime string) (io.Reader, error)
}
Policy enforces upload security constraints, format whitelists, and size boundaries.
type PresignOptions ¶
type PresignOptions struct {
// Expiry is the validity duration of the presigned URL. Default is 15 minutes.
Expiry time.Duration
// ContentType specifies the expected Content-Type header to constrain PUT presigned URLs.
ContentType string
// ContentDisposition specifies the expected Content-Disposition header.
ContentDisposition string
// QueryParams allows passing additional query parameters if supported.
QueryParams url.Values
}
PresignOptions configures parameters for URL presigning.
type PresignedURL ¶
type PresignedURL struct {
// URL is the signed HTTP address.
URL string `json:"url"`
// Method is the expected HTTP verb (e.g. "GET" or "PUT").
Method string `json:"method"`
// ExpiresAt is the timestamp when the signature becomes invalid.
ExpiresAt time.Time `json:"expires_at"`
// SignedHeaders contains any required HTTP headers that were included in the signature calculation.
SignedHeaders map[string]string `json:"signed_headers,omitempty"`
}
PresignedURL contains a time-limited signed URL for direct client access or uploads.
type PutOptions ¶
type PutOptions struct {
// ID is an optional predetermined logical ID. If empty, a UUIDv7 is generated automatically.
ID string
// Key is an optional explicit physical storage key. If empty, KeyGenerator determines it.
Key string
// Namespace partitions objects logically (e.g. "avatars", "bots/autorespon", "media").
Namespace string
// OwnerID identifies the owner/tenant of the object.
OwnerID string
// Filename is the original client filename (e.g. "report.pdf"), used for Content-Disposition & MIME hints.
Filename string
// ContentType is the MIME type. If empty, BlobKit sniffs up to the first 512 bytes.
ContentType string
// Size is the known payload size in bytes. Set to SizeUnknown (-1) if unknown or streaming.
Size int64
// ExplicitSize indicates that Size was intentionally specified (even if 0),
// allowing distinction between an unassigned size (streaming) and an explicit 0-byte upload.
ExplicitSize bool
// Visibility controls whether the object is public or private. Defaults to VisibilityPrivate.
Visibility Visibility
// Metadata contains custom user key-value metadata to store alongside the object.
Metadata map[string]string
// ContentDisposition customizes the Content-Disposition HTTP header.
ContentDisposition string
// CacheControl customizes the Cache-Control HTTP header (e.g. "public, max-age=31536000, immutable").
CacheControl string
// RetentionUntil locks the object against deletion or modification until this timestamp.
RetentionUntil *time.Time
// ExpiresAt marks the object to expire automatically after this timestamp.
ExpiresAt *time.Time
// LegalHold marks the object with an active legal hold.
LegalHold bool
// ClientChecksum specifies an expected payload SHA-256 hash to enforce on upload.
ClientChecksum string
// VerifyIntegrity forces BlobKit to stream-hash and verify the payload SHA-256 during upload.
VerifyIntegrity bool
// Policy overrides client-wide upload validation rules for this specific upload.
Policy *Policy
// Provider forces the upload to use a specific registered driver instead of the router policy.
Provider string
}
PutOptions configures an upload operation, conveying semantic intent.
type ReconciliationReport ¶
type ReconciliationReport struct {
TotalChecked int64 `json:"total_checked"`
OrphanObjects []string `json:"orphan_objects"` // present in storage but missing in registry
GhostRecords []string `json:"ghost_records"` // present in registry (StateCommitted) but missing in storage
MismatchedSize []string `json:"mismatched_size"` // length mismatch between registry and storage
Repaired int64 `json:"repaired"` // records or objects repaired (when dryRun is false)
}
ReconciliationReport records orphan objects, ghost records, and repaired inconsistencies.
type Record ¶
type Record struct {
// ObjectID is the immutable logical identifier (UUIDv7) and primary database key.
ObjectID string `json:"object_id"`
// Namespace partitions objects logically (e.g. "avatars", "bots/autorespon", "media").
Namespace string `json:"namespace"`
// OwnerID identifies the tenant, user, or bot owning this object.
OwnerID string `json:"owner_id,omitempty"`
// Key is the physical storage key inside the provider's bucket.
Key string `json:"key"`
// Bucket is the storage bucket name.
Bucket string `json:"bucket"`
// Provider is the identifier of the driver holding the bytes (e.g. "r2-primary").
Provider string `json:"provider"`
// MIMEType is the verified Content-Type of the blob.
MIMEType string `json:"mime_type"`
// Size is the content length in bytes.
Size int64 `json:"size"`
// ChecksumSHA256 is the hex-encoded SHA-256 payload digest.
ChecksumSHA256 string `json:"checksum_sha256,omitempty"`
// ETag is the HTTP entity tag from the storage provider.
ETag string `json:"etag,omitempty"`
// OriginalFilename is the client-facing filename (e.g. "photo.png").
OriginalFilename string `json:"original_filename,omitempty"`
// Visibility specifies access level (public or private).
Visibility Visibility `json:"visibility"`
// Status indicates lifecycle state (pending, committed, deleted).
Status LifecycleState `json:"status"`
// Metadata holds arbitrary user-defined key-value attributes.
Metadata map[string]string `json:"metadata,omitempty"`
// RetentionUntil specifies when retention lock expires.
RetentionUntil *time.Time `json:"retention_until,omitempty"`
// ExpiresAt specifies when the object automatically expires.
ExpiresAt *time.Time `json:"expires_at,omitempty"`
// LegalHold prevents deletion or modification when true.
LegalHold bool `json:"legal_hold,omitempty"`
// ClientChecksum is the client-provided checksum (if any).
ClientChecksum string `json:"client_checksum,omitempty"`
// CreatedAt is the logical creation timestamp.
CreatedAt time.Time `json:"created_at"`
// UpdatedAt is the last modification timestamp.
UpdatedAt time.Time `json:"updated_at"`
// DeletedAt records when the object was marked deleted (if soft-deleted).
DeletedAt *time.Time `json:"deleted_at,omitempty"`
}
Record represents the canonical metadata and indexing record stored in the database registry. NOTE: Full URL is explicitly omitted from canonical record storage, as URLs are delivery/access details dynamically constructed by BlobKit when requested (CDN or presigned).
type RouteContext ¶
type RouteContext struct {
// Op is the current operation.
Op Operation
// Key is the target physical storage key (if known).
Key string
// Namespace is the semantic category/partition (e.g. "avatars", "backups").
Namespace string
// ForcedProvider is an optional explicit provider name requested by the caller.
ForcedProvider string
}
RouteContext carries routing intent from the application or BlobKit core to the router.
type Router ¶
type Router interface {
// Select resolves the appropriate driver for the given operation context.
Select(ctx context.Context, rc RouteContext) (Driver, error)
// AllDrivers returns all registered drivers under this router.
AllDrivers() []Driver
// ReportFailure notifies the router of an execution failure for health tracking.
ReportFailure(driverName string, err error)
// ReportSuccess notifies the router of a successful execution.
ReportSuccess(driverName string)
}
Router determines which storage provider driver should execute an operation.
type S3PathResolver ¶
type S3PathResolver struct {
// contains filtered or unexported fields
}
S3PathResolver formats standard path-style or virtual-hosted URLs for S3 endpoints.
func NewS3PathResolver ¶
func NewS3PathResolver(endpoint, bucket string) *S3PathResolver
NewS3PathResolver returns an S3PathResolver.
func (*S3PathResolver) ResolveURL ¶
func (s *S3PathResolver) ResolveURL(key string) string
ResolveURL builds a path-style URL: endpoint/bucket/key.
type SeekableReader ¶
type SeekableReader struct {
// contains filtered or unexported fields
}
SeekableReader implements io.ReadSeekCloser and io.ReaderAt over an object storage key using HTTP Byte-Range requests ("Range: bytes=start-end").
It enables fast, on-demand random-access seeking (e.g. for ZIP parsing, Parquet query engines, audio/video streaming, or PDF reading) without downloading the entire object into memory or disk.
func (*SeekableReader) Close ¶
func (s *SeekableReader) Close() error
Close closes any open active stream connections.
func (*SeekableReader) Read ¶
func (s *SeekableReader) Read(p []byte) (int, error)
Read reads up to len(p) bytes from the remote object starting at the current cursor.
func (*SeekableReader) ReadAt ¶
func (s *SeekableReader) ReadAt(p []byte, off int64) (int, error)
ReadAt reads len(p) bytes into p at offset off without modifying the seeker's cursor. It implements io.ReaderAt and is safe for concurrent execution across goroutines.
func (*SeekableReader) Seek ¶
func (s *SeekableReader) Seek(offset int64, whence int) (int64, error)
Seek sets the offset for the next Read, adhering to the standard io.Seeker contract.
func (*SeekableReader) Size ¶
func (s *SeekableReader) Size() int64
Size returns the total size of the remote object in bytes.
type SessionState ¶
type SessionState string
SessionState represents the lifecycle status of a resumable multipart upload session.
const ( // SessionActive indicates the upload session is open and receiving parts. SessionActive SessionState = "active" // SessionCommitted indicates the upload session has been finalized into an object. SessionCommitted SessionState = "committed" // SessionAborted indicates the upload session was cancelled or cleaned up. SessionAborted SessionState = "aborted" )
type SizeReader ¶
type SizeReader struct {
// contains filtered or unexported fields
}
SizeReader wraps an io.Reader to enforce expected payload size constraints. If exact is true (or expectedSize >= 0), it returns ErrSizeMismatch if the stream yields fewer bytes than expected or has surplus bytes beyond expectedSize.
func NewSizeReader ¶
func NewSizeReader(r io.Reader, expectedSize int64, exact bool) *SizeReader
NewSizeReader constructs a SizeReader. If exact is true and expectedSize >= 0, the reader strictly verifies byte parity. If expectedSize < 0, size verification is disabled (pass-through).
func (*SizeReader) Read ¶
func (sr *SizeReader) Read(p []byte) (n int, err error)
Read implements io.Reader with strict boundary checking.
func (*SizeReader) TotalRead ¶
func (sr *SizeReader) TotalRead() int64
TotalRead returns the total number of bytes read so far.
func (*SizeReader) Verify ¶
func (sr *SizeReader) Verify() error
Verify checks whether the reader was read to completion and matched expectedSize.
type StorageError ¶
StorageError represents a standardized, sanitized error returned by BlobKit operations. It wraps the underlying driver error without leaking sensitive endpoint credentials or internal network topologies.
func (*StorageError) Error ¶
func (e *StorageError) Error() string
Error formats the sanitized error message.
func (*StorageError) Is ¶
func (e *StorageError) Is(target error) bool
Is reports whether the target matches this error or its wrapped error.
func (*StorageError) Unwrap ¶
func (e *StorageError) Unwrap() error
Unwrap returns the underlying error.
type URLResolver ¶
URLResolver maps a storage object key to an accessible public or CDN URL.
type UploadSession ¶
type UploadSession struct {
// ID is the unique identifier of the session (UUIDv7).
ID string `json:"id"`
// ObjectID is the logical object ID being constructed.
ObjectID string `json:"object_id"`
// Key is the physical storage key in the bucket.
Key string `json:"key"`
// Bucket is the target bucket name.
Bucket string `json:"bucket"`
// Provider is the storage driver managing the multipart upload.
Provider string `json:"provider"`
// UploadID is the underlying driver's multipart upload identifier.
UploadID string `json:"upload_id"`
// PartSize is the planned byte size per chunk (typically >= 5MB).
PartSize int64 `json:"part_size"`
// TotalSize is the optional declared total object size, or 0 if unknown.
TotalSize int64 `json:"total_size"`
// Parts tracks all successfully uploaded parts for this session.
Parts []CompletedPart `json:"parts"`
// ExpiresAt specifies when this session becomes stale and eligible for auto-cleanup.
ExpiresAt time.Time `json:"expires_at"`
// CreatedAt is the timestamp when the session was initiated.
CreatedAt time.Time `json:"created_at"`
// Status indicates whether the session is active, committed, or aborted.
Status SessionState `json:"status"`
}
UploadSession encapsulates the state required to track, resume, or abort a multipart upload.
type ValidationInput ¶
type ValidationInput struct {
Namespace string
Filename string
ContentType string
Size int64
ExplicitSize bool // ExplicitSize indicates that Size was explicitly specified (even if 0)
SizeKnown bool // SizeKnown indicates that the payload size is deterministically known
StreamReader io.Reader
}
ValidationInput supplies parameters for policy enforcement.
type Visibility ¶
type Visibility string
Visibility defines the access control scope of an object.
const ( // VisibilityPublic marks the object as publicly deliverable via CDN or bucket public endpoint. VisibilityPublic Visibility = "public" // VisibilityPrivate marks the object as private, requiring presigned URLs or authenticated streams. VisibilityPrivate Visibility = "private" )