serve http: fix serving files of unknown length

Before this change serving files of unknown length were always
returned as 0 length files.

This change serves them correctly, but does not support Range:
requests on them.

See: https://forum.rclone.org/t/serve-http-behavior-when-the-size-is-unknown/21319
This commit is contained in:
Nick Craig-Wood 2020-12-26 20:59:45 +00:00
parent f7404f52e7
commit 629c0d0f65

View File

@ -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
}
}
}