Add serve from rclone; add readiness check for each debrid, rather than waiting for all to be ready
This commit is contained in:
@@ -10,6 +10,7 @@ type WebDav struct {
|
|||||||
DownloadLinksRefreshInterval string `json:"download_links_refresh_interval,omitempty"`
|
DownloadLinksRefreshInterval string `json:"download_links_refresh_interval,omitempty"`
|
||||||
Workers int `json:"workers,omitempty"`
|
Workers int `json:"workers,omitempty"`
|
||||||
AutoExpireLinksAfter string `json:"auto_expire_links_after,omitempty"`
|
AutoExpireLinksAfter string `json:"auto_expire_links_after,omitempty"`
|
||||||
|
ServeFromRclone bool `json:"serve_from_rclone,omitempty"`
|
||||||
|
|
||||||
// Folder
|
// Folder
|
||||||
FolderNaming string `json:"folder_naming,omitempty"`
|
FolderNaming string `json:"folder_naming,omitempty"`
|
||||||
|
|||||||
@@ -168,6 +168,10 @@ func (c *Cache) IsReady() chan struct{} {
|
|||||||
return c.ready
|
return c.ready
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cache) StreamWithRclone() bool {
|
||||||
|
return c.config.ServeFromRclone
|
||||||
|
}
|
||||||
|
|
||||||
// Reset clears all internal state so the Cache can be reused without leaks.
|
// Reset clears all internal state so the Cache can be reused without leaks.
|
||||||
// Call this after stopping the old Cache (so no goroutines are holding references),
|
// Call this after stopping the old Cache (so no goroutines are holding references),
|
||||||
// and before you discard the instance on a restart.
|
// and before you discard the instance on a restart.
|
||||||
|
|||||||
@@ -357,7 +357,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="form-check me-3">
|
<div class="form-check me-3">
|
||||||
<input type="checkbox" class="form-check-input addSamples" name="debrid[${index}].add_samples" id="debrid[${index}].add_samples">
|
<input type="checkbox" class="form-check-input" name="debrid[${index}].add_samples" id="debrid[${index}].add_samples">
|
||||||
<label class="form-check-label" for="debrid[${index}].add_samples">Add Samples</label>
|
<label class="form-check-label" for="debrid[${index}].add_samples">Add Samples</label>
|
||||||
</div>
|
</div>
|
||||||
<small class="form-text text-muted">Add samples, extras etc when adding torrent to debrid(disabled by default)</small>
|
<small class="form-text text-muted">Add samples, extras etc when adding torrent to debrid(disabled by default)</small>
|
||||||
@@ -370,14 +370,15 @@
|
|||||||
<small class="form-text text-muted">Create an internal webdav for this debrid</small>
|
<small class="form-text text-muted">Create an internal webdav for this debrid</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-3 webdav d-none">
|
<div class="webdav d-none">
|
||||||
<h6 class="pb-2">Webdav</h6>
|
<h6 class="pb-2">Webdav</h6>
|
||||||
<div class="col-md-2 mb-3">
|
<div class="row mt-3">
|
||||||
|
<div class="col-md-3 mb-3">
|
||||||
<label class="form-label" for="debrid[${index}].torrents_refresh_interval">Torrents Refresh Interval</label>
|
<label class="form-label" for="debrid[${index}].torrents_refresh_interval">Torrents Refresh Interval</label>
|
||||||
<input type="text" class="form-control webdav-field" name="debrid[${index}].torrents_refresh_interval" id="debrid[${index}].torrents_refresh_interval" placeholder="15s" value="15s">
|
<input type="text" class="form-control webdav-field" name="debrid[${index}].torrents_refresh_interval" id="debrid[${index}].torrents_refresh_interval" placeholder="15s" value="15s">
|
||||||
<small class="form-text text-muted">How often to refresh the torrents list from debrid(instant when using webdav)</small>
|
<small class="form-text text-muted">How often to refresh the torrents list from debrid</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2 mb-3">
|
<div class="col-md-3 mb-3">
|
||||||
<label class="form-label" for="debrid[${index}].download_links_refresh_interval">Links Refresh Interval</label>
|
<label class="form-label" for="debrid[${index}].download_links_refresh_interval">Links Refresh Interval</label>
|
||||||
<input type="text" class="form-control webdav-field" name="debrid[${index}].download_links_refresh_interval" id="debrid[${index}].download_links_refresh_interval" placeholder="40m" value="40m">
|
<input type="text" class="form-control webdav-field" name="debrid[${index}].download_links_refresh_interval" id="debrid[${index}].download_links_refresh_interval" placeholder="40m" value="40m">
|
||||||
<small class="form-text text-muted">How often to refresh the download links list from debrid</small>
|
<small class="form-text text-muted">How often to refresh the download links list from debrid</small>
|
||||||
@@ -387,7 +388,7 @@
|
|||||||
<input type="text" class="form-control webdav-field" name="debrid[${index}].auto_expire_links_after" id="debrid[${index}].auto_expire_links_after" placeholder="3d" value="3d">
|
<input type="text" class="form-control webdav-field" name="debrid[${index}].auto_expire_links_after" id="debrid[${index}].auto_expire_links_after" placeholder="3d" value="3d">
|
||||||
<small class="form-text text-muted">How long to keep the links in the webdav before expiring</small>
|
<small class="form-text text-muted">How long to keep the links in the webdav before expiring</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2 mb-3">
|
<div class="col-md-3 mb-3">
|
||||||
<label class="form-label" for="debrid[${index}].workers">Number of Workers</label>
|
<label class="form-label" for="debrid[${index}].workers">Number of Workers</label>
|
||||||
<input type="text" class="form-control webdav-field" name="debrid[${index}].workers" id="debrid[${index}].workers" placeholder="e.g., 50" value="50">
|
<input type="text" class="form-control webdav-field" name="debrid[${index}].workers" id="debrid[${index}].workers" placeholder="e.g., 50" value="50">
|
||||||
<small class="form-text text-muted">Number of workers to use for the webdav server(when refreshing)</small>
|
<small class="form-text text-muted">Number of workers to use for the webdav server(when refreshing)</small>
|
||||||
@@ -424,6 +425,15 @@
|
|||||||
<input type="password" class="form-control webdav-field" name="debrid[${index}].rc_pass" id="debrid[${index}].rc_pass">
|
<input type="password" class="form-control webdav-field" name="debrid[${index}].rc_pass" id="debrid[${index}].rc_pass">
|
||||||
<small class="form-text text-muted">Rclone RC Password for the webdav server</small>
|
<small class="form-text text-muted">Rclone RC Password for the webdav server</small>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-3 mb-3">
|
||||||
|
<div class="form-check me-3">
|
||||||
|
<input type="checkbox" class="form-check-input" name="debrid[${index}].serve_from_rclone" id="debrid[${index}].serve_from_rclone">
|
||||||
|
<label class="form-check-label" for="debrid[${index}].serve_from_rclone">Serve From Rclone</label>
|
||||||
|
</div>
|
||||||
|
<small class="form-text text-muted">Rclone handles serving/streaming the download link</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-3">
|
||||||
<div class="col mt-3">
|
<div class="col mt-3">
|
||||||
<h6 class="pb-2">Custom Folders</h6>
|
<h6 class="pb-2">Custom Folders</h6>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
@@ -437,6 +447,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
// Template for directory entries (with filter buttons for both positive and negative variants)
|
// Template for directory entries (with filter buttons for both positive and negative variants)
|
||||||
@@ -1096,6 +1107,7 @@
|
|||||||
debrid.rc_user = document.querySelector(`[name="debrid[${i}].rc_user"]`).value;
|
debrid.rc_user = document.querySelector(`[name="debrid[${i}].rc_user"]`).value;
|
||||||
debrid.rc_pass = document.querySelector(`[name="debrid[${i}].rc_pass"]`).value;
|
debrid.rc_pass = document.querySelector(`[name="debrid[${i}].rc_pass"]`).value;
|
||||||
debrid.rc_refresh_dirs = document.querySelector(`[name="debrid[${i}].rc_refresh_dirs"]`).value;
|
debrid.rc_refresh_dirs = document.querySelector(`[name="debrid[${i}].rc_refresh_dirs"]`).value;
|
||||||
|
debrid.serve_from_rclone = document.querySelector(`[name="debrid[${i}].serve_from_rclone"]`).checked;
|
||||||
|
|
||||||
//custom folders
|
//custom folders
|
||||||
debrid.directories = {};
|
debrid.directories = {};
|
||||||
|
|||||||
+1
-1
@@ -202,7 +202,7 @@ func (f *File) Read(p []byte) (n int, err error) {
|
|||||||
// Make the request to get the file
|
// Make the request to get the file
|
||||||
resp, err := f.stream()
|
resp, err := f.stream()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, io.EOF
|
return 0, err
|
||||||
}
|
}
|
||||||
if resp == nil {
|
if resp == nil {
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
|
|||||||
@@ -45,6 +45,20 @@ func (h *Handler) Mkdir(ctx context.Context, name string, perm os.FileMode) erro
|
|||||||
return os.ErrPermission // Read-only filesystem
|
return os.ErrPermission // Read-only filesystem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handler) readinessMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
select {
|
||||||
|
case <-h.cache.IsReady():
|
||||||
|
// WebDAV is ready, proceed
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
default:
|
||||||
|
// WebDAV is still initializing
|
||||||
|
w.Header().Set("Retry-After", "5")
|
||||||
|
http.Error(w, "WebDAV service is initializing, please try again shortly", http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// RemoveAll implements webdav.FileSystem
|
// RemoveAll implements webdav.FileSystem
|
||||||
func (h *Handler) RemoveAll(ctx context.Context, name string) error {
|
func (h *Handler) RemoveAll(ctx context.Context, name string) error {
|
||||||
if name[0] != '/' {
|
if name[0] != '/' {
|
||||||
@@ -399,6 +413,7 @@ func (h *Handler) handleGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Debug().
|
h.logger.Debug().
|
||||||
Err(err).
|
Err(err).
|
||||||
|
Str("link", file.link).
|
||||||
Str("path", r.URL.Path).
|
Str("path", r.URL.Path).
|
||||||
Msg("Could not fetch download link")
|
Msg("Could not fetch download link")
|
||||||
http.Error(w, "Could not fetch download link", http.StatusPreconditionFailed)
|
http.Error(w, "Could not fetch download link", http.StatusPreconditionFailed)
|
||||||
@@ -409,6 +424,11 @@ func (h *Handler) handleGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
file.downloadLink = link
|
file.downloadLink = link
|
||||||
|
if h.cache.StreamWithRclone() {
|
||||||
|
// Redirect to the download link
|
||||||
|
http.Redirect(w, r, file.downloadLink, http.StatusFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rs, ok := fRaw.(io.ReadSeeker)
|
rs, ok := fRaw.(io.ReadSeeker)
|
||||||
|
|||||||
@@ -153,7 +153,10 @@ func (wd *WebDav) Start(ctx context.Context) error {
|
|||||||
|
|
||||||
func (wd *WebDav) mountHandlers(r chi.Router) {
|
func (wd *WebDav) mountHandlers(r chi.Router) {
|
||||||
for _, h := range wd.Handlers {
|
for _, h := range wd.Handlers {
|
||||||
r.Mount("/"+h.Name, h) // Mount to /name since router is already prefixed with /webdav
|
r.Route("/"+h.Name, func(r chi.Router) {
|
||||||
|
r.Use(h.readinessMiddleware)
|
||||||
|
r.Mount("/", h)
|
||||||
|
}) // Mount to /name since router is already prefixed with /webdav
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user