Skip to content

Commit

Permalink
fileserver: support simple Range headers
Browse files Browse the repository at this point in the history
This is sufficient to allow efficient media streaming.

Specifically, these two header forms are supported for content that does
not have an injector:

Range: bytes N-
Range: bytes N-M

Partial fix for cortesi#42
  • Loading branch information
rmmh committed Apr 23, 2024
1 parent 98a1cca commit ccc5e7a
Showing 1 changed file with 23 additions and 0 deletions.
23 changes: 23 additions & 0 deletions fileserver/fileserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"os"
"path"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
Expand All @@ -27,6 +28,8 @@ import (

const sniffLen = 512

var simpleRangeRegexp = regexp.MustCompile(`^bytes=(\d+)-(\d*)$`)

func rawHeaderGet(h http.Header, key string) string {
if v := h[key]; len(v) > 0 {
return v[0]
Expand Down Expand Up @@ -148,6 +151,26 @@ func serveContent(ci inject.CopyInject, w http.ResponseWriter, r *http.Request,
}
}

rangeopt := r.Header.Get("Range")
if rangeopt != "" && !injector.Found() && r.Method == "GET" {
m := simpleRangeRegexp.FindStringSubmatch(rangeopt)
if m != nil {
start, err1 := strconv.ParseInt(m[1], 10, 64)
end, err2 := strconv.ParseInt(m[2], 10, 64)
if err2 != nil {
end = size - 1
}

if err1 == nil && start <= end && end < size {
w.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", start, end, size))
w.WriteHeader(206)
content.Seek(start, io.SeekStart)
_, err = io.CopyN(w, content, end-start+1)
return err
}
}
}

w.WriteHeader(code)
if r.Method != "HEAD" {
_, err := injector.Copy(w)
Expand Down

0 comments on commit ccc5e7a

Please sign in to comment.