feat: add independent platform modules and multi-provider storage
This commit is contained in:
68
storage/storage.go
Normal file
68
storage/storage.go
Normal file
@@ -0,0 +1,68 @@
|
||||
// Package storage defines streaming object storage; callers own returned bodies.
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var ErrNotFound = errors.New("storage: object not found")
|
||||
var ErrTooLarge = errors.New("storage: object exceeds limit")
|
||||
|
||||
type Info struct {
|
||||
Key string `json:"key"`
|
||||
Size int64 `json:"size"`
|
||||
ContentType string `json:"contentType"`
|
||||
ModifiedAt time.Time `json:"modifiedAt"`
|
||||
}
|
||||
type Object struct {
|
||||
Info
|
||||
Body io.ReadCloser
|
||||
}
|
||||
type Store interface {
|
||||
Put(context.Context, string, io.Reader, int64, string) (Info, error)
|
||||
Get(context.Context, string) (Object, error)
|
||||
Delete(context.Context, string) error
|
||||
}
|
||||
|
||||
// Presigner is an optional capability. URLs grant temporary read access and
|
||||
// must not be logged. Providers may expire them earlier when credentials expire.
|
||||
type Presigner interface {
|
||||
PresignGet(context.Context, string, time.Duration) (*url.URL, error)
|
||||
}
|
||||
|
||||
func Check(ctx context.Context, key string) error {
|
||||
if ctx == nil {
|
||||
return errors.New("storage: nil context")
|
||||
}
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
if key == "" || len(key) > 1024 || !utf8.ValidString(key) || strings.Contains(key, "\\") || strings.IndexFunc(key, unicode.IsControl) >= 0 {
|
||||
return errors.New("storage: invalid key")
|
||||
}
|
||||
for _, part := range strings.Split(key, "/") {
|
||||
if part == "" || part == "." || part == ".." {
|
||||
return errors.New("storage: invalid key path")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ContextReader struct {
|
||||
Context context.Context
|
||||
Reader io.Reader
|
||||
}
|
||||
|
||||
func (r ContextReader) Read(p []byte) (int, error) {
|
||||
if err := r.Context.Err(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return r.Reader.Read(p)
|
||||
}
|
||||
Reference in New Issue
Block a user