Files
dobotai-platform/internal/outboundimage/stable_handler.go

49 lines
1.6 KiB
Go

package outboundimage
import (
"context"
"errors"
"net/http"
"path"
"strconv"
"strings"
)
type ObjectReader interface {
Get(ctx context.Context, key string, maxBytes int64) ([]byte, string, error)
}
func NewStableImageHandler(reader ObjectReader, objectPrefix, routePrefix string, maxBytes int64) (http.Handler, error) {
objectPrefix = strings.Trim(strings.TrimSpace(objectPrefix), "/")
routePrefix = "/" + strings.Trim(strings.TrimSpace(routePrefix), "/") + "/"
if reader == nil || objectPrefix == "" || maxBytes <= 0 {
return nil, errors.New("outbound image: invalid stable image handler configuration")
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet && r.Method != http.MethodHead {
w.Header().Set("Allow", "GET, HEAD")
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
return
}
id := strings.TrimPrefix(r.URL.Path, routePrefix)
if r.URL.Path == id || strings.Contains(id, "/") || !stableImageIDRE.MatchString(id) {
http.NotFound(w, r)
return
}
data, contentType, err := reader.Get(r.Context(), path.Join(objectPrefix, id), maxBytes)
if err != nil || len(data) == 0 || imageExtension(contentType) == "" {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", strings.TrimSpace(strings.Split(contentType, ";")[0]))
w.Header().Set("Content-Length", strconv.Itoa(len(data)))
w.Header().Set("Cache-Control", "public, max-age=86400, immutable")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.WriteHeader(http.StatusOK)
if r.Method == http.MethodHead {
return
}
_, _ = w.Write(data)
}), nil
}