feat: slice cache 200 code

pull/250/head
zijiren233 4 months ago
parent c68dc2065d
commit 91a8779aa1

@ -9,6 +9,8 @@ import (
"slices"
"strconv"
"strings"
"github.com/synctv-org/synctv/utils"
)
var (
@ -33,6 +35,7 @@ type HttpReadSeekCloser struct {
contentLength int64
length int64
currentRespMaxOffset int64
notSupportRange bool
}
type HttpReadSeekerConf func(h *HttpReadSeekCloser)
@ -131,7 +134,7 @@ func NewHttpReadSeekCloser(url string, conf ...HttpReadSeekerConf) *HttpReadSeek
contentLength: -1,
method: http.MethodGet,
headMethod: http.MethodHead,
length: 64 * 1024, // Default length
length: 1024 * 1024 * 16,
headers: make(http.Header),
ctx: context.Background(),
client: http.DefaultClient,
@ -225,7 +228,22 @@ func (h *HttpReadSeekCloser) FetchNextChunk() error {
return fmt.Errorf("do request: %w", err)
}
if resp.StatusCode != http.StatusPartialContent && resp.StatusCode != http.StatusOK {
if resp.StatusCode == http.StatusOK {
if h.contentLength < 0 {
h.contentLength = resp.ContentLength
resp.Body.Close()
return h.FetchNextChunk()
}
if h.offset > 0 {
resp.Body.Close()
return fmt.Errorf("not support range")
}
h.notSupportRange = true
h.currentRespMaxOffset = h.contentLength - 1
return nil
}
if resp.StatusCode != http.StatusPartialContent {
resp.Body.Close()
return fmt.Errorf("status code: %d", resp.StatusCode)
}
@ -235,19 +253,13 @@ func (h *HttpReadSeekCloser) FetchNextChunk() error {
return fmt.Errorf("check response: %w", err)
}
switch resp.StatusCode {
case http.StatusPartialContent:
contentTotalLength, err := ParseContentRangeTotalLength(resp.Header.Get("Content-Range"))
if err == nil && contentTotalLength > 0 {
h.contentLength = contentTotalLength
}
_, end, err := ParseContentRangeStartAndEnd(resp.Header.Get("Content-Range"))
if err == nil {
h.currentRespMaxOffset = end
}
case http.StatusOK:
h.contentLength = resp.ContentLength
h.currentRespMaxOffset = h.contentLength - 1
contentTotalLength, err := ParseContentRangeTotalLength(resp.Header.Get("Content-Range"))
if err == nil && contentTotalLength > 0 {
h.contentLength = contentTotalLength
}
_, end, err := ParseContentRangeStartAndEnd(resp.Header.Get("Content-Range"))
if err == nil && end != -1 {
h.currentRespMaxOffset = end
}
h.contentType = resp.Header.Get("Content-Type")
@ -267,6 +279,8 @@ func (h *HttpReadSeekCloser) createRequest() (*http.Request, error) {
end = h.contentLength - 1
}
h.currentRespMaxOffset = end
req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", h.offset, end))
return req, nil
}
@ -277,6 +291,10 @@ func (h *HttpReadSeekCloser) createRequestWithoutRange() (*http.Request, error)
return nil, err
}
req.Header = h.headers.Clone()
req.Header.Del("Range")
if req.Header.Get("User-Agent") == "" {
req.Header.Set("User-Agent", utils.UA)
}
return req, nil
}
@ -337,6 +355,9 @@ func (h *HttpReadSeekCloser) Seek(offset int64, whence int) (int64, error) {
}
func (h *HttpReadSeekCloser) calculateNewOffset(offset int64, whence int) (int64, error) {
if offset != 0 && h.notSupportRange {
return 0, fmt.Errorf("not support range")
}
switch whence {
case io.SeekStart:
return offset, nil
@ -367,6 +388,10 @@ func (h *HttpReadSeekCloser) fetchContentLength() error {
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("status code: %d", resp.StatusCode)
}
if err := h.checkResponse(resp); err != nil {
return err
}
@ -435,17 +460,15 @@ func ParseContentRangeStartAndEnd(contentRange string) (int64, int64, error) {
return 0, 0, fmt.Errorf("invalid content range start: %w", err)
}
end, err := strconv.ParseInt(strings.TrimSpace(rangeParts[1]), 10, 64)
if err != nil {
return 0, 0, fmt.Errorf("invalid content range end: %w", err)
}
if start < 0 || end < 0 {
return 0, 0, fmt.Errorf("negative content range bounds: start=%d, end=%d", start, end)
}
if start > end {
return 0, 0, fmt.Errorf("invalid content range bounds: start=%d > end=%d", start, end)
rangeParts[1] = strings.TrimSpace(rangeParts[1])
var end int64
if rangeParts[1] == "" || rangeParts[1] == "*" {
end = -1
} else {
end, err = strconv.ParseInt(rangeParts[1], 10, 64)
if err != nil {
return 0, 0, fmt.Errorf("invalid content range end: %w", err)
}
}
return start, end, nil

Loading…
Cancel
Save