nezha/script/patch/fs.patch

103 lines
3.6 KiB
Diff
Raw Normal View History

2024-12-31 10:58:44 -05:00
@@ -249,9 +249,24 @@
}
return size, nil
}
- serveContent(w, req, name, modtime, sizeFunc, content)
+ serveContent(w, req, name, modtime, sizeFunc, content, StatusOK)
}
+func ServeContentCustomStatusCode(w ResponseWriter, req *Request, name string, modtime time.Time, content io.ReadSeeker, code int) {
+ sizeFunc := func() (int64, error) {
+ size, err := content.Seek(0, io.SeekEnd)
+ if err != nil {
+ return 0, errSeeker
+ }
+ _, err = content.Seek(0, io.SeekStart)
+ if err != nil {
+ return 0, errSeeker
+ }
+ return size, nil
+ }
+ serveContent(w, req, name, modtime, sizeFunc, content, code)
+}
+
// errSeeker is returned by ServeContent's sizeFunc when the content
// doesn't seek properly. The underlying Seeker's error text isn't
// included in the sizeFunc reply so it's not sent over HTTP to end
@@ -266,15 +281,13 @@
// if modtime.IsZero(), modtime is unknown.
// content must be seeked to the beginning of the file.
// The sizeFunc is called at most once. Its error, if any, is sent in the HTTP response.
-func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time, sizeFunc func() (int64, error), content io.ReadSeeker) {
+func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time, sizeFunc func() (int64, error), content io.ReadSeeker, code int) {
setLastModified(w, modtime)
done, rangeReq := checkPreconditions(w, r, modtime)
if done {
return
}
- code := StatusOK
-
// If Content-Type isn't set, use the file's extension to find it, but
// if the Content-Type is unset explicitly, do not sniff the type.
ctypes, haveType := w.Header()["Content-Type"]
@@ -671,7 +684,7 @@
}
// name is '/'-separated, not filepath.Separator.
-func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool) {
+func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool, statusCode int) {
const indexPage = "/index.html"
// redirect .../index.html to .../
@@ -753,7 +766,7 @@
// serveContent will check modification time
sizeFunc := func() (int64, error) { return d.Size(), nil }
- serveContent(w, r, d.Name(), d.ModTime(), sizeFunc, f)
+ serveContent(w, r, d.Name(), d.ModTime(), sizeFunc, f, statusCode)
}
// toHTTPError returns a non-specific HTTP error message and status code
@@ -814,7 +827,21 @@
return
}
dir, file := filepath.Split(name)
- serveFile(w, r, Dir(dir), file, false)
+ serveFile(w, r, Dir(dir), file, false, StatusOK)
+}
+
+func ServeFileWithCustomStatusCode(w ResponseWriter, r *Request, name string, statusCode int) {
+ 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).
+ serveError(w, "invalid URL path", StatusBadRequest)
+ return
+ }
+ dir, file := filepath.Split(name)
+ serveFile(w, r, Dir(dir), file, false, statusCode)
}
// ServeFileFS replies to the request with the contents
@@ -847,7 +874,7 @@
serveError(w, "invalid URL path", StatusBadRequest)
return
}
- serveFile(w, r, FS(fsys), name, false)
+ serveFile(w, r, FS(fsys), name, false, StatusOK)
}
func containsDotDot(v string) bool {
@@ -983,7 +1010,7 @@
upath = "/" + upath
r.URL.Path = upath
}
- serveFile(w, r, f.root, path.Clean(upath), true)
+ serveFile(w, r, f.root, path.Clean(upath), true, StatusOK)
}
// httpRange specifies the byte range to be sent to the client.