- Add etags to stream url

- Support for non-File files with range instead of readint to memory
- Log more errors for reealdebrid
This commit is contained in:
Mukhtar Akere
2025-05-22 22:23:49 +01:00
parent 7c1defc684
commit d10a6ddedd
2 changed files with 35 additions and 14 deletions

View File

@@ -502,7 +502,7 @@ func (r *RealDebrid) _getDownloadLink(file *types.File) (*types.DownloadLink, er
} }
var data ErrorResponse var data ErrorResponse
if err = json.Unmarshal(b, &data); err != nil { if err = json.Unmarshal(b, &data); err != nil {
return nil, err return nil, fmt.Errorf("error unmarshalling %d || %s \n %s", resp.StatusCode, err, string(b))
} }
switch data.ErrorCode { switch data.ErrorCode {
case 19: case 19:

View File

@@ -1,10 +1,10 @@
package webdav package webdav
import ( import (
"bytes"
"context" "context"
"fmt" "fmt"
"io" "io"
"mime"
"net/http" "net/http"
"os" "os"
"path" "path"
@@ -388,6 +388,7 @@ func (h *Handler) handleGet(w http.ResponseWriter, r *http.Request) {
defer func(fRaw webdav.File) { defer func(fRaw webdav.File) {
err := fRaw.Close() err := fRaw.Close()
if err != nil { if err != nil {
h.logger.Error().Err(err).Msg("Failed to close file")
return return
} }
}(fRaw) }(fRaw)
@@ -426,27 +427,47 @@ func (h *Handler) handleGet(w http.ResponseWriter, r *http.Request) {
file.downloadLink = link file.downloadLink = link
if h.cache.StreamWithRclone() { if h.cache.StreamWithRclone() {
// Redirect to the download link // Redirect to the download link
http.Redirect(w, r, file.downloadLink, http.StatusFound) http.Redirect(w, r, file.downloadLink, http.StatusTemporaryRedirect)
return return
} }
} }
// ETags
etag := fmt.Sprintf("\"%x-%x\"", fi.ModTime().Unix(), fi.Size())
w.Header().Set("ETag", etag)
// 7. Content-Type by extension
ext := filepath.Ext(fi.Name())
contentType := mime.TypeByExtension(ext)
if contentType == "" {
contentType = "application/octet-stream"
}
w.Header().Set("Content-Type", contentType)
rs, ok := fRaw.(io.ReadSeeker) rs, ok := fRaw.(io.ReadSeeker)
if !ok { if !ok {
// If not, read the entire file into memory as a fallback. if r.Header.Get("Range") != "" {
buf, err := io.ReadAll(fRaw) http.Error(w, "Range not supported", http.StatusRequestedRangeNotSatisfiable)
if err != nil {
h.logger.Error().Err(err).Msg("Failed to read file content")
http.Error(w, "Server Error", http.StatusInternalServerError)
return return
} }
rs = bytes.NewReader(buf) w.Header().Set("Content-Length", fmt.Sprintf("%d", fi.Size()))
w.Header().Set("Last-Modified", fi.ModTime().UTC().Format(http.TimeFormat))
w.Header().Set("Accept-Ranges", "bytes")
ctx := r.Context()
done := make(chan struct{})
go func() {
defer close(done)
io.Copy(w, fRaw)
}()
select {
case <-ctx.Done():
h.logger.Debug().Msg("Client cancelled download")
return
case <-done:
}
return
} }
fileName := fi.Name() http.ServeContent(w, r, fi.Name(), fi.ModTime(), rs)
contentType := getContentType(fileName)
w.Header().Set("Content-Type", contentType)
// http.ServeContent automatically handles Range requests.
http.ServeContent(w, r, fileName, fi.ModTime(), rs)
} }
func (h *Handler) handleHead(w http.ResponseWriter, r *http.Request) { func (h *Handler) handleHead(w http.ResponseWriter, r *http.Request) {