package storage
import (
"context"
"errors"
"fmt"
"io"
"regexp"
"strings"
)
var ErrNotExist = errors.New("storage: object does not exist")
type Storage interface {
Get(ctx context.Context, key string) (io.ReadCloser, error)
Put(ctx context.Context, key string, r io.Reader) error
Delete(ctx context.Context, key string) error
}
// StatStorage provides the exact stored object size without downloading it.
type StatStorage interface {
Stat(ctx context.Context, key string) (int64, error)
}
// ConditionalStorage writes only when key does not already exist.
type ConditionalStorage interface {
Storage
PutIfAbsent(ctx context.Context, key string, r io.Reader) error
}
var keyRe = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._:/@%+=-]{0,511}$`)
func ValidateKey(key string) error {
if !keyRe.MatchString(key) {
return fmt.Errorf("storage: invalid key %q", key)
}
for _, seg := range strings.Split(key, "/") {
if seg == "" || seg == "." || seg == ".." {
return fmt.Errorf("storage: invalid key %q", key)
}
}
return nil
}