Files
dobotai-platform/internal/outboundimage/publisher.go
T

66 lines
1.8 KiB
Go

package outboundimage
import (
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"path"
"strings"
"time"
)
type ObjectStore interface {
Put(ctx context.Context, key string, data []byte, contentType string) error
PresignGet(ctx context.Context, key string, ttl time.Duration) (string, error)
}
type HashPublisher struct {
store ObjectStore
prefix string
ttl time.Duration
}
func NewHashPublisher(store ObjectStore, prefix string, ttl time.Duration) *HashPublisher {
return &HashPublisher{store: store, prefix: strings.Trim(strings.TrimSpace(prefix), "/"), ttl: ttl}
}
func (p *HashPublisher) Publish(ctx context.Context, data []byte, contentType string) (string, error) {
if p == nil || p.store == nil || len(data) == 0 || p.prefix == "" || p.ttl <= 0 {
return "", errors.New("outbound image: invalid publisher configuration")
}
extension := imageExtension(contentType)
if extension == "" {
return "", errors.New("outbound image: unsupported image content type")
}
sum := sha256.Sum256(data)
digest := hex.EncodeToString(sum[:])
key := path.Join(p.prefix, digest[:2], digest+extension)
if err := p.store.Put(ctx, key, data, contentType); err != nil {
return "", errors.New("outbound image: publish object failed")
}
signedURL, err := p.store.PresignGet(ctx, key, p.ttl)
if err != nil {
return "", errors.New("outbound image: sign object URL failed")
}
if !strings.HasPrefix(strings.TrimSpace(signedURL), "https://") {
return "", errors.New("outbound image: signed object URL must use HTTPS")
}
return signedURL, nil
}
func imageExtension(contentType string) string {
switch strings.ToLower(strings.TrimSpace(strings.Split(contentType, ";")[0])) {
case "image/jpeg", "image/jpg":
return ".jpg"
case "image/png":
return ".png"
case "image/webp":
return ".webp"
case "image/gif":
return ".gif"
default:
return ""
}
}