diff --git a/cmd/serve/http/http.go b/cmd/serve/http/http.go index 04724174a..f64b4bc55 100644 --- a/cmd/serve/http/http.go +++ b/cmd/serve/http/http.go @@ -1,6 +1,7 @@ package http import ( + "io" "net/http" "os" "path" @@ -172,8 +173,11 @@ func (s *server) serveFile(w http.ResponseWriter, r *http.Request, remote string obj := entry.(fs.Object) file := node.(*vfs.File) - // Set content length since we know how long the object is - w.Header().Set("Content-Length", strconv.FormatInt(node.Size(), 10)) + // Set content length if we know how long the object is + knownSize := obj.Size() >= 0 + if knownSize { + w.Header().Set("Content-Length", strconv.FormatInt(node.Size(), 10)) + } // Set content type mimeType := fs.MimeType(r.Context(), obj) @@ -210,5 +214,19 @@ func (s *server) serveFile(w http.ResponseWriter, r *http.Request, remote string // FIXME in = fs.NewAccount(in, obj).WithBuffer() // account the transfer // Serve the file - http.ServeContent(w, r, remote, node.ModTime(), in) + if knownSize { + http.ServeContent(w, r, remote, node.ModTime(), in) + } else { + // http.ServeContent can't serve unknown length files + if rangeRequest := r.Header.Get("Range"); rangeRequest != "" { + http.Error(w, "Can't use Range: on files of unknown length", http.StatusRequestedRangeNotSatisfiable) + return + } + n, err := io.Copy(w, in) + if err != nil { + fs.Errorf(obj, "Didn't finish writing GET request (wrote %d/unknown bytes): %v", n, err) + return + } + } + }