diff --git a/backend/webdav/webdav.go b/backend/webdav/webdav.go index 4611e3370..f3e2ee905 100644 --- a/backend/webdav/webdav.go +++ b/backend/webdav/webdav.go @@ -159,7 +159,9 @@ Set to 0 to disable chunked uploading. Help: "Exclude ownCloud mounted storages", Advanced: true, Default: false, - }}, + }, + fshttp.UnixSocketConfig, + }, }) } @@ -177,6 +179,7 @@ type Options struct { ChunkSize fs.SizeSuffix `config:"nextcloud_chunk_size"` ExcludeShares bool `config:"owncloud_exclude_shares"` ExcludeMounts bool `config:"owncloud_exclude_mounts"` + UnixSocket string `config:"unix_socket"` } // Fs represents a remote webdav @@ -458,7 +461,12 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e precision: fs.ModTimeNotSupported, } - client := fshttp.NewClient(ctx) + var client *http.Client + if opt.UnixSocket == "" { + client = fshttp.NewClient(ctx) + } else { + client = fshttp.NewClientWithUnixSocket(ctx, opt.UnixSocket) + } if opt.Vendor == "sharepoint-ntlm" { // Disable transparent HTTP/2 support as per https://golang.org/pkg/net/http/ , // otherwise any connection to IIS 10.0 fails with 'stream error: stream ID 39; HTTP_1_1_REQUIRED' diff --git a/cmd/serve/webdav/webdav.go b/cmd/serve/webdav/webdav.go index c28b13e69..622575e8d 100644 --- a/cmd/serve/webdav/webdav.go +++ b/cmd/serve/webdav/webdav.go @@ -115,6 +115,19 @@ Create a new DWORD BasicAuthLevel with value 2. https://learn.microsoft.com/en-us/office/troubleshoot/powerpoint/office-opens-blank-from-sharepoint +### Serving over a unix socket + +You can serve the webdav on a unix socket like this: + + rclone serve webdav --addr unix:///tmp/my.socket remote:path + +and connect to it like this using rclone and the webdav backend: + + rclone --webdav-unix-socket /tmp/my.socket --webdav-url http://localhost lsf :webdav: + +Note that there is no authentication on http protocol - this is expected to be +done by the permissions on the socket. + ` + libhttp.Help(flagPrefix) + libhttp.TemplateHelp(flagPrefix) + libhttp.AuthHelp(flagPrefix) + vfs.Help() + proxy.Help, Annotations: map[string]string{ "versionIntroduced": "v1.39", diff --git a/docs/content/webdav.md b/docs/content/webdav.md index 458a3488c..c42fcd57b 100644 --- a/docs/content/webdav.md +++ b/docs/content/webdav.md @@ -294,6 +294,17 @@ Properties: - Type: bool - Default: false +#### --webdav-unix-socket + +Path to a unix domain socket to dial to, instead of opening a TCP connection directly + +Properties: + +- Config: unix_socket +- Env Var: RCLONE_WEBDAV_UNIX_SOCKET +- Type: string +- Required: false + #### --webdav-description Description of the remote. diff --git a/fs/fshttp/http.go b/fs/fshttp/http.go index be9e3aee3..5a3fea073 100644 --- a/fs/fshttp/http.go +++ b/fs/fshttp/http.go @@ -31,6 +31,14 @@ var ( noTransport = new(sync.Once) cookieJar, _ = cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) logMutex sync.Mutex + + // UnixSocketConfig describes the option to configure the path to a unix domain socket to connect to + UnixSocketConfig = fs.Option{ + Name: "unix_socket", + Help: "Path to a unix domain socket to dial to, instead of opening a TCP connection directly", + Advanced: true, + Default: "", + } ) // ResetTransport resets the existing transport, allowing it to take new settings. @@ -134,9 +142,15 @@ func NewTransport(ctx context.Context) http.RoundTripper { // NewClient returns an http.Client with the correct timeouts func NewClient(ctx context.Context) *http.Client { + return NewClientCustom(ctx, nil) +} + +// NewClientCustom returns an http.Client with the correct timeouts. +// It allows customizing the transport, using NewTransportCustom. +func NewClientCustom(ctx context.Context, customize func(*http.Transport)) *http.Client { ci := fs.GetConfig(ctx) client := &http.Client{ - Transport: NewTransport(ctx), + Transport: NewTransportCustom(ctx, customize), } if ci.Cookie { client.Jar = cookieJar @@ -144,6 +158,17 @@ func NewClient(ctx context.Context) *http.Client { return client } +// NewClientWithUnixSocket returns an http.Client with the correct timeout. +// It internally uses NewClientCustom with a custom dialer connecting to +// the specified unix domain socket. +func NewClientWithUnixSocket(ctx context.Context, path string) *http.Client { + return NewClientCustom(ctx, func(t *http.Transport) { + t.DialContext = func(reqCtx context.Context, network, addr string) (net.Conn, error) { + return NewDialer(ctx).DialContext(reqCtx, "unix", path) + } + }) +} + // Transport is our http Transport which wraps an http.Transport // * Sets the User Agent // * Does logging