]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/net/http/fs.go
net/http: set/override Content-Length for encoded range requests
[gostls13.git] / src / net / http / fs.go
index 55094400ac7f2ee68dfa7aeb0a522b68c31e3c26..20da56001cf691a1b4c42f65b73d2fc017a7cf50 100644 (file)
@@ -343,19 +343,12 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
        }
 
        w.Header().Set("Accept-Ranges", "bytes")
-       if w.Header().Get("Content-Encoding") == "" {
-               w.Header().Set("Content-Length", strconv.FormatInt(sendSize, 10))
-       }
+       w.Header().Set("Content-Length", strconv.FormatInt(sendSize, 10))
 
        w.WriteHeader(code)
 
-       if r.Method != MethodHead {
-               if sendSize == size {
-                       // use Copy in the non-range case to make use of WriterTo if available
-                       io.Copy(w, sendContent)
-               } else {
-                       io.CopyN(w, sendContent, sendSize)
-               }
+       if r.Method != "HEAD" {
+               io.CopyN(w, sendContent, sendSize)
        }
 }
 
@@ -746,6 +739,40 @@ func ServeFile(w ResponseWriter, r *Request, name string) {
        serveFile(w, r, Dir(dir), file, false)
 }
 
+// ServeFileFS replies to the request with the contents
+// of the named file or directory from the file system fsys.
+//
+// If the provided file or directory name is a relative path, it is
+// interpreted relative to the current directory and may ascend to
+// parent directories. If the provided name is constructed from user
+// input, it should be sanitized before calling ServeFile.
+//
+// As a precaution, ServeFile will reject requests where r.URL.Path
+// contains a ".." path element; this protects against callers who
+// might unsafely use filepath.Join on r.URL.Path without sanitizing
+// it and then use that filepath.Join result as the name argument.
+//
+// As another special case, ServeFile redirects any request where r.URL.Path
+// ends in "/index.html" to the same path, without the final
+// "index.html". To avoid such redirects either modify the path or
+// use ServeContent.
+//
+// Outside of those two special cases, ServeFile does not use
+// r.URL.Path for selecting the file or directory to serve; only the
+// file or directory provided in the name argument is used.
+func ServeFileFS(w ResponseWriter, r *Request, fsys fs.FS, name string) {
+       if containsDotDot(r.URL.Path) {
+               // Too many programs use r.URL.Path to construct the argument to
+               // serveFile. Reject the request under the assumption that happened
+               // here and ".." may not be wanted.
+               // Note that name might not contain "..", for example if code (still
+               // incorrectly) used filepath.Join(myDir, r.URL.Path).
+               Error(w, "invalid URL path", StatusBadRequest)
+               return
+       }
+       serveFile(w, r, FS(fsys), name, false)
+}
+
 func containsDotDot(v string) bool {
        if !strings.Contains(v, "..") {
                return false
@@ -855,13 +882,23 @@ func FS(fsys fs.FS) FileSystem {
 //
 //     http.Handle("/", http.FileServer(http.Dir("/tmp")))
 //
-// To use an fs.FS implementation, use http.FS to convert it:
-//
-//     http.Handle("/", http.FileServer(http.FS(fsys)))
+// To use an fs.FS implementation, use http.FileServerFS instead.
 func FileServer(root FileSystem) Handler {
        return &fileHandler{root}
 }
 
+// FileServerFS returns a handler that serves HTTP requests
+// with the contents of the file system fsys.
+//
+// As a special case, the returned file server redirects any request
+// ending in "/index.html" to the same path, without the final
+// "index.html".
+//
+//     http.Handle("/", http.FileServerFS(fsys))
+func FileServerFS(root fs.FS) Handler {
+       return FileServer(FS(root))
+}
+
 func (f *fileHandler) ServeHTTP(w ResponseWriter, r *Request) {
        upath := r.URL.Path
        if !strings.HasPrefix(upath, "/") {