diff options
| author | Rose Hogenson <rosehogenson@posteo.net> | 2026-01-03 11:41:44 -0800 |
|---|---|---|
| committer | Rose Hogenson <rosehogenson@posteo.net> | 2026-01-03 11:41:44 -0800 |
| commit | 96253cbcb61569aafb59d592150dfb47e7cb43ff (patch) | |
| tree | 2980b363ac9a6003e3a78c9dd3430097c4bc9642 | |
| parent | d5e2bf19b5bbdf35e4088677a571910e015b48b9 (diff) | |
| download | roseh.moe-96253cbcb61569aafb59d592150dfb47e7cb43ff.tar.zst | |
Support range requests for wormhole downloads
| -rw-r--r-- | default.nix | 2 | ||||
| -rw-r--r-- | go.mod | 2 | ||||
| -rw-r--r-- | go.sum | 4 | ||||
| -rw-r--r-- | roseh.moe.go | 33 |
4 files changed, 23 insertions, 18 deletions
diff --git a/default.nix b/default.nix index 3f75480..269e821 100644 --- a/default.nix +++ b/default.nix @@ -16,5 +16,5 @@ pkgs.buildGoModule rec { # remember to bump this hash when your dependencies change. # vendorHash = pkgs.lib.fakeHash; - vendorHash = "sha256-w6HhPvISsk/a6WC/T9Ml02SCZ8LXaTKVp5brPkx7Aec="; + vendorHash = "sha256-J5cVBGeQ7lLVd4KMkbwDdpnCckW/t9m1Y2V9Y5PjEIs="; } @@ -6,7 +6,7 @@ require ( github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e golang.org/x/term v0.38.0 roseh.moe/pkg/ccl v1.0.1 - roseh.moe/pkg/oae2 v0.0.2 + roseh.moe/pkg/oae2 v0.1.0 roseh.moe/pkg/wordlist v1.0.2 ) @@ -8,7 +8,7 @@ golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= roseh.moe/pkg/ccl v1.0.1 h1:jD8d45xlyB3OphhSI9qoMvKAohyQ2Xtq52NPOnqBWtE= roseh.moe/pkg/ccl v1.0.1/go.mod h1:OCcZ30pQDtjXgqgpN8eLo6f/pTi6XVKIHPs1k+gups0= -roseh.moe/pkg/oae2 v0.0.2 h1:h/anygogeuOAFp9tVDP5RNlEo/n4lEgpyVOe+0QSix8= -roseh.moe/pkg/oae2 v0.0.2/go.mod h1:SZ5K2nvKreVdhHVNxujxcZLOnjhVi+qPi2XkB18dR8g= +roseh.moe/pkg/oae2 v0.1.0 h1:mGkGIHErlnykRZZ1dvHd73/gVjPudIEoXxdJ133GKeM= +roseh.moe/pkg/oae2 v0.1.0/go.mod h1:SZ5K2nvKreVdhHVNxujxcZLOnjhVi+qPi2XkB18dR8g= roseh.moe/pkg/wordlist v1.0.2 h1:riB2RqCU5zXfCQjaPHYTXV/688FV9/Bp6Hnb0IAkP9c= roseh.moe/pkg/wordlist v1.0.2/go.mod h1:2Jd7j6Qy5SElcrITJJNUcbxH9TPKYn0k+BJL3tsJdiY= diff --git a/roseh.moe.go b/roseh.moe.go index 55e2682..b134de0 100644 --- a/roseh.moe.go +++ b/roseh.moe.go @@ -265,15 +265,22 @@ func writeHoleFile(part *multipart.Part) (string, error) { return hole, f.Close() } -func decryptedSize(size int64) int64 { - size -= 32 - segments := (size + (blockSize - 1)) / blockSize - return size - segments*16 +type offsetReader struct { + io.ReadSeeker + offset int +} + +func (r *offsetReader) Seek(offset int64, whence int) (int64, error) { + if whence == io.SeekStart { + offset += int64(r.offset) + } + n, err := r.ReadSeeker.Seek(offset, whence) + return n - int64(r.offset), err } var errNoHole = errors.New("no such hole") -func readHoleFile(w http.ResponseWriter, hole string) error { +func readHoleFile(w http.ResponseWriter, req *http.Request, hole string) error { key, err := hkdf.Key(sha256.New, []byte(hole), nil, "", 48) if err != nil { return err @@ -287,10 +294,6 @@ func readHoleFile(w http.ResponseWriter, hole string) error { return err } defer f.Close() - stat, err := f.Stat() - if err != nil { - return err - } r := oae2.NewReader(f, encryptionKey, blockSize) buf := make([]byte, 8) if _, err := io.ReadFull(r, buf); err != nil { @@ -303,10 +306,12 @@ func readHoleFile(w http.ResponseWriter, hole string) error { } fileName := string(buf) w.Header().Set("Content-Disposition", "attachment; filename*=UTF-8''"+fileName) - fileSize := decryptedSize(stat.Size()) - 8 - int64(fileNameLen) - w.Header().Set("Content-Length", strconv.FormatInt(fileSize, 10)) - _, err = io.Copy(w, r) - return err + var modTime time.Time + if stat, err := f.Stat(); err == nil { + modTime = stat.ModTime() + } + http.ServeContent(w, req, fileName, modTime, &offsetReader{r, 8 + int(fileNameLen)}) + return nil } func wormhole(w http.ResponseWriter, r *http.Request) { @@ -362,7 +367,7 @@ func wormholeUpload(w http.ResponseWriter, r *http.Request) { } func wormholeDownload(w http.ResponseWriter, r *http.Request) { - if err := readHoleFile(w, r.PathValue("hole")); err != nil { + if err := readHoleFile(w, r, r.PathValue("hole")); err != nil { if err == errNoHole { notFound(w, r) return |
