mirror of
https://github.com/Noooste/garage-ui.git
synced 2026-07-26 07:48:13 +00:00
c0976a1e1d
* feat(preview): implement object preview functionality with token-based access * docs: update README to include inline object preview feature * test: add range read error handling and attachment content disposition tests
69 lines
1.6 KiB
Go
69 lines
1.6 KiB
Go
package handlers
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// byteRange is a resolved, inclusive byte range within an object.
|
|
type byteRange struct {
|
|
start int64
|
|
end int64
|
|
}
|
|
|
|
// parseRangeHeader resolves a Range request header against the object size.
|
|
// It supports a single "bytes=" range in its three forms: start-end, start-,
|
|
// and -suffix. A nil result with unsatisfiable false means serve the full
|
|
// object with 200; absent, malformed, and multi-range headers all land there,
|
|
// which RFC 9110 permits. unsatisfiable true means respond 416.
|
|
func parseRangeHeader(header string, size int64) (rng *byteRange, unsatisfiable bool) {
|
|
spec, ok := strings.CutPrefix(header, "bytes=")
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
spec = strings.TrimSpace(spec)
|
|
if strings.Contains(spec, ",") {
|
|
return nil, false
|
|
}
|
|
startStr, endStr, ok := strings.Cut(spec, "-")
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
startStr = strings.TrimSpace(startStr)
|
|
endStr = strings.TrimSpace(endStr)
|
|
|
|
// Suffix form "-n" asks for the last n bytes.
|
|
if startStr == "" {
|
|
n, err := strconv.ParseInt(endStr, 10, 64)
|
|
if err != nil {
|
|
return nil, false
|
|
}
|
|
if n <= 0 || size == 0 {
|
|
return nil, true
|
|
}
|
|
if n > size {
|
|
n = size
|
|
}
|
|
return &byteRange{start: size - n, end: size - 1}, false
|
|
}
|
|
|
|
start, err := strconv.ParseInt(startStr, 10, 64)
|
|
if err != nil || start < 0 {
|
|
return nil, false
|
|
}
|
|
if start >= size {
|
|
return nil, true
|
|
}
|
|
if endStr == "" {
|
|
return &byteRange{start: start, end: size - 1}, false
|
|
}
|
|
end, err := strconv.ParseInt(endStr, 10, 64)
|
|
if err != nil || end < start {
|
|
return nil, false
|
|
}
|
|
if end >= size {
|
|
end = size - 1
|
|
}
|
|
return &byteRange{start: start, end: end}, false
|
|
}
|