From a0dff2dd9cc6a67c6042639abdf7f958a4313a64 Mon Sep 17 00:00:00 2001 From: DanielEgbers <27849724+DanielEgbers@users.noreply.github.com> Date: Mon, 5 Feb 2024 12:48:51 +0100 Subject: [PATCH] Seafile: Fix download/upload error when FILE_SERVER_ROOT is relative A seafile server can be configured to use a relative URL as FILE_SERVER_ROOT in order to support more than one hostname/ip. (see https://github.com/haiwen/seahub/issues/3398#issuecomment-506920360 ) The previous backend implementation always expected an absolute download/upload URL, resulting in an "unsupported protocol scheme" error. With this commit it supports both absolute and relative. --- backend/seafile/webapi.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/backend/seafile/webapi.go b/backend/seafile/webapi.go index d3ebe3fde..1cc05a14b 100644 --- a/backend/seafile/webapi.go +++ b/backend/seafile/webapi.go @@ -577,7 +577,7 @@ func (f *Fs) getDownloadLink(ctx context.Context, libraryID, filePath string) (s return result, nil } -func (f *Fs) download(ctx context.Context, url string, size int64, options ...fs.OpenOption) (io.ReadCloser, error) { +func (f *Fs) download(ctx context.Context, downloadLink string, size int64, options ...fs.OpenOption) (io.ReadCloser, error) { // Check if we need to download partial content var start, end int64 = 0, size partialContent := false @@ -606,11 +606,18 @@ func (f *Fs) download(ctx context.Context, url string, size int64, options ...fs // Build the http request opts := rest.Opts{ Method: "GET", - RootURL: url, Options: options, } + parsedURL, err := url.Parse(downloadLink) + if err != nil { + return nil, fmt.Errorf("failed to parse download url: %w", err) + } + if parsedURL.IsAbs() { + opts.RootURL = downloadLink + } else { + opts.Path = downloadLink + } var resp *http.Response - var err error err = f.pacer.Call(func() (bool, error) { resp, err = f.srv.Call(ctx, &opts) return f.shouldRetry(ctx, resp, err) @@ -618,7 +625,7 @@ func (f *Fs) download(ctx context.Context, url string, size int64, options ...fs if err != nil { if resp != nil { if resp.StatusCode == 404 { - return nil, fmt.Errorf("file not found '%s'", url) + return nil, fmt.Errorf("file not found '%s'", downloadLink) } } return nil, err @@ -688,11 +695,19 @@ func (f *Fs) upload(ctx context.Context, in io.Reader, uploadLink, filePath stri opts := rest.Opts{ Method: "POST", - RootURL: uploadLink, Body: formReader, ContentType: contentType, Parameters: url.Values{"ret-json": {"1"}}, // It needs to be on the url, not in the body parameters } + parsedURL, err := url.Parse(uploadLink) + if err != nil { + return nil, fmt.Errorf("failed to parse upload url: %w", err) + } + if parsedURL.IsAbs() { + opts.RootURL = uploadLink + } else { + opts.Path = uploadLink + } result := make([]api.FileDetail, 1) var resp *http.Response // If an error occurs during the call, do not attempt to retry: The upload link is single use only