Skip to content

Commit

Permalink
webdav: introduce unix_socket_path
Browse files Browse the repository at this point in the history
This adds a new optional parameter to the backend, allowing to specify a
path to a unix domain socket to connect to, instead the specified URL.

If the parameter is set, we use `fshttp.NewClientCustom` to modify the
HTTP transport, to use a dialer connecting to the unix domain socket
path specified for that backend.

The URL itself is still used for the rest of the HTTP client, allowing
host and subpath to stay intact.

This allows using rclone with the webdav backend to connect to a WebDAV
server provided at a Unix Domain socket:

```
RCLONE_WEBDAV_UNIX_SOCKET_PATH=/path/to/my.sock \
RCLONE_WEBDAV_URL=http://localhost \
rclone sync mydir :webdav:/somewhere
```
  • Loading branch information
flokli committed May 24, 2024
1 parent 8f1c309 commit 9c1f017
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 2 deletions.
19 changes: 18 additions & 1 deletion backend/webdav/webdav.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"errors"
"fmt"
"io"
"net"
"net/http"
"net/url"
"os/exec"
Expand Down Expand Up @@ -159,6 +160,11 @@ Set to 0 to disable chunked uploading.
Help: "Exclude ownCloud mounted storages",
Advanced: true,
Default: false,
}, {
Name: "unix_socket_path",
Help: "Path to a unix domain socket to dial to, instead of opening a TCP connection directly",
Advanced: true,
Default: "",
}},
})
}
Expand All @@ -177,6 +183,7 @@ type Options struct {
ChunkSize fs.SizeSuffix `config:"nextcloud_chunk_size"`
ExcludeShares bool `config:"owncloud_exclude_shares"`
ExcludeMounts bool `config:"owncloud_exclude_mounts"`
UnixSocketPath string `config:"unix_socket_path"`
}

// Fs represents a remote webdav
Expand Down Expand Up @@ -458,7 +465,17 @@ 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.UnixSocketPath == "" {
client = fshttp.NewClient(ctx)
} else {
fs.Debugf(f, "custom unix_socket_path configured (%v), updating dialer…", opt.UnixSocketPath)
client = fshttp.NewClientCustom(ctx, func(t *http.Transport) {
t.DialContext = func(reqCtx context.Context, network, addr string) (net.Conn, error) {
return fshttp.NewDialer(ctx).DialContext(reqCtx, "unix", opt.UnixSocketPath)
}
})
}
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'
Expand Down
11 changes: 11 additions & 0 deletions docs/content/webdav.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,17 @@ Properties:
- Type: bool
- Default: false

#### --webdav-unix-socket-path

Path to a unix domain socket to dial to, instead of opening a TCP connection directly

Properties:

- Config: unix_socket_path
- Env Var: RCLONE_WEBDAV_UNIX_SOCKET_PATH
- Type: string
- Required: false

#### --webdav-description

Description of the remote
Expand Down
1 change: 1 addition & 0 deletions fs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ type ConfigInfo struct {
Inplace bool // Download directly to destination file instead of atomic download to temp/rename
PartialSuffix string
MetadataMapper SpaceSepList
UnixSocketPath string // Optional unix socket to connect to
}

// NewConfig creates a new config with everything set to the default
Expand Down
8 changes: 7 additions & 1 deletion fs/fshttp/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,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
Expand Down

0 comments on commit 9c1f017

Please sign in to comment.