~james/core

core/spindle/storage/storage.go -rw-r--r-- 1.0 KiB
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 17 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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
}