package storage import ( "context" "errors" "fmt" "io" "path/filepath" "regexp" "strings" "tangled.org/core/spindle/config" ) 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 } 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 } func New(ctx context.Context, cfg *config.Config) (Storage, error) { switch cfg.Cache.Backend { case "": return nil, nil case "disk": dir := cfg.Cache.DiskDir if dir == "" { dir = filepath.Join(filepath.Dir(cfg.Server.DBPath), "cache") } return NewDisk(dir) case "s3": return NewS3(ctx, cfg.Cache.S3Bucket, cfg.Cache.S3Prefix) default: return nil, fmt.Errorf("storage: unknown backend %q", cfg.Cache.Backend) } }