1
0
Fork 0
photos/pkg/bucket/bucket.go

77 lines
1.5 KiB
Go

package bucket
import (
"errors"
"fmt"
"net/url"
"strings"
)
type Bucket string
const bucketMetadataPrefix = "metadata/"
var ErrorInvalidBucket = errors.New("invalid bucket")
func (b Bucket) Validate() error {
// Ensure is URL
u, err := url.ParseRequestURI(string(b))
if err != nil {
return fmt.Errorf("%w: %w: %v", ErrorInvalidBucket, err, b)
}
if u.Scheme != "http" && u.Scheme != "https" {
return fmt.Errorf("%w: %v", ErrorInvalidBucket, b)
}
if u.Host == "" || !strings.HasSuffix(u.Path, "/") {
return fmt.Errorf("%w: %v", ErrorInvalidBucket, b)
}
return nil
}
func (b Bucket) String() string {
return string(b)
}
func (b Bucket) URL(p Pathable) *url.URL {
u, _ := url.ParseRequestURI(string(b))
path := p.Path()
u.Path = pathJoin(u.Path, path.Path)
u.RawQuery = path.RawQuery
return u
}
func pathJoin(paths ...string) string {
cleanedPaths := make([]string, 0, len(paths))
for i, path := range paths {
cleanedPath := strings.TrimPrefix(path, "/")
if i != len(paths)-1 {
cleanedPath = strings.TrimSuffix(cleanedPath, "/")
}
if i == 0 && len(cleanedPath) == 0 {
continue
}
cleanedPaths = append(cleanedPaths, cleanedPath)
}
return "/" + strings.Join(cleanedPaths, "/")
}
type Pathable interface {
Path() *url.URL
}
type BucketMetadata string
func (b Bucket) Metadata(name string) BucketMetadata {
return BucketMetadata(bucketMetadataPrefix + name)
}
func (m BucketMetadata) String() string {
return string(m)
}
func (m BucketMetadata) Path() *url.URL {
return &url.URL{
Path: string(m),
}
}