serve: refactor VFS and proxy handling into Provider

This commit is contained in:
Hakan İSMAİL
2026-08-18 09:03:12 +01:00
committed by Nick Craig-Wood
parent a1f98b49df
commit f425f8d466
6 changed files with 200 additions and 101 deletions
+20 -15
View File
@@ -170,8 +170,7 @@ type driver struct {
srv *ftp.Server srv *ftp.Server
ctx context.Context // for global config ctx context.Context // for global config
opt Options opt Options
globalVFS *vfs.VFS // the VFS if not using auth proxy provider *proxy.Provider
proxy *proxy.Proxy // may be nil if not in use
useTLS bool useTLS bool
userPassMu sync.Mutex // to protect userPass userPassMu sync.Mutex // to protect userPass
userPass map[string]string // cache of username => password when using vfs proxy userPass map[string]string // cache of username => password when using vfs proxy
@@ -195,15 +194,19 @@ func newServer(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Opt
} }
d := &driver{ d := &driver{
f: f, f: f,
ctx: ctx, ctx: ctx,
opt: *opt, opt: *opt,
provider: proxy.NewProvider(ctx, f, vfsOpt, proxyOpt),
} }
if proxy.Opt.AuthProxy != "" { defer func() {
d.proxy = proxy.New(ctx, proxyOpt, vfsOpt) if err != nil {
d.provider.Shutdown()
}
}()
if d.provider.IsProxy() {
d.userPass = make(map[string]string, 16) d.userPass = make(map[string]string, 16)
} else {
d.globalVFS = vfs.New(ctx, f, vfsOpt)
} }
d.useTLS = d.opt.TLSKey != "" d.useTLS = d.opt.TLSKey != ""
@@ -250,7 +253,9 @@ func (d *driver) Serve() error {
//lint:ignore U1000 unused when not building linux //lint:ignore U1000 unused when not building linux
func (d *driver) Shutdown() error { func (d *driver) Shutdown() error {
fs.Logf(d.f, "Stopping FTP on %s", d.srv.Hostname+":"+strconv.Itoa(d.srv.Port)) fs.Logf(d.f, "Stopping FTP on %s", d.srv.Hostname+":"+strconv.Itoa(d.srv.Port))
return d.srv.Shutdown() err := d.srv.Shutdown()
d.provider.Shutdown()
return err
} }
// Return the first address of the server // Return the first address of the server
@@ -316,8 +321,8 @@ func (l *Logger) PrintResponse(sessionID string, code int, message string) {
// CheckPasswd handle auth based on configuration // CheckPasswd handle auth based on configuration
func (d *driver) CheckPasswd(sctx *ftp.Context, user, pass string) (ok bool, err error) { func (d *driver) CheckPasswd(sctx *ftp.Context, user, pass string) (ok bool, err error) {
if d.proxy != nil { if d.provider.IsProxy() {
_, _, err = d.proxy.Call(user, pass, false, sctx.Sess.RemoteAddr().String()) _, _, err = d.provider.Proxy().Call(user, pass, false, sctx.Sess.RemoteAddr().String())
if err != nil { if err != nil {
fs.Infof(nil, "proxy login failed: %v", err) fs.Infof(nil, "proxy login failed: %v", err)
return false, nil return false, nil
@@ -351,9 +356,9 @@ func (d *driver) CheckPasswd(sctx *ftp.Context, user, pass string) (ok bool, err
// Get the VFS for this connection // Get the VFS for this connection
func (d *driver) getVFS(sctx *ftp.Context) (VFS *vfs.VFS, err error) { func (d *driver) getVFS(sctx *ftp.Context) (VFS *vfs.VFS, err error) {
if d.proxy == nil { if !d.provider.IsProxy() {
// If no proxy always use the same VFS // If no proxy always use the same VFS
return d.globalVFS, nil return d.provider.VFS(), nil
} }
user := sctx.Sess.LoginUser() user := sctx.Sess.LoginUser()
d.userPassMu.Lock() d.userPassMu.Lock()
@@ -366,7 +371,7 @@ func (d *driver) getVFS(sctx *ftp.Context) (VFS *vfs.VFS, err error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
VFS, _, err = d.proxy.Call(user, pass, false, sctx.Sess.RemoteAddr().String()) VFS, _, err = d.provider.Proxy().Call(user, pass, false, sctx.Sess.RemoteAddr().String())
if err != nil { if err != nil {
return nil, fmt.Errorf("proxy login failed: %w", err) return nil, fmt.Errorf("proxy login failed: %w", err)
} }
+20 -29
View File
@@ -4,7 +4,6 @@ package http
import ( import (
"context" "context"
_ "embed" _ "embed"
"errors"
"fmt" "fmt"
"io" "io"
"net" "net"
@@ -150,33 +149,21 @@ control the stats printing.
// HTTP contains everything to run the server // HTTP contains everything to run the server
type HTTP struct { type HTTP struct {
f fs.Fs f fs.Fs
_vfs *vfs.VFS // don't use directly, use getVFS provider *proxy.Provider
server *libhttp.Server server *libhttp.Server
opt Options opt Options
proxy *proxy.Proxy ctx context.Context // for global config
ctx context.Context // for global config
} }
// Gets the VFS in use for this request // Gets the VFS in use for this request
func (s *HTTP) getVFS(ctx context.Context) (VFS *vfs.VFS, err error) { func (s *HTTP) getVFS(ctx context.Context) (VFS *vfs.VFS, err error) {
if s._vfs != nil { return s.provider.Get(ctx)
return s._vfs, nil
}
value := libhttp.CtxGetAuth(ctx)
if value == nil {
return nil, errors.New("no VFS found in context")
}
VFS, ok := value.(*vfs.VFS)
if !ok {
return nil, fmt.Errorf("context value is not VFS: %#v", value)
}
return VFS, nil
} }
// auth does proxy authorization // auth does proxy authorization
func (s *HTTP) auth(r *http.Request, user, pass string) (value any, err error) { func (s *HTTP) auth(r *http.Request, user, pass string) (value any, err error) {
VFS, _, err := s.proxy.Call(user, pass, false, r.RemoteAddr) VFS, _, err := s.provider.Proxy().Call(user, pass, false, r.RemoteAddr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -185,17 +172,19 @@ func (s *HTTP) auth(r *http.Request, user, pass string) (value any, err error) {
func newServer(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Options, proxyOpt *proxy.Options) (s *HTTP, err error) { func newServer(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Options, proxyOpt *proxy.Options) (s *HTTP, err error) {
s = &HTTP{ s = &HTTP{
f: f, f: f,
ctx: ctx, ctx: ctx,
opt: *opt, opt: *opt,
provider: proxy.NewProvider(ctx, f, vfsOpt, proxyOpt),
} }
defer func() {
if err != nil {
s.provider.Shutdown()
}
}()
if proxyOpt.AuthProxy != "" { if s.provider.IsProxy() {
s.proxy = proxy.New(ctx, proxyOpt, vfsOpt)
// override auth
s.opt.Auth.CustomAuthFn = s.auth s.opt.Auth.CustomAuthFn = s.auth
} else {
s._vfs = vfs.New(ctx, f, vfsOpt)
} }
s.server, err = libhttp.NewServer(ctx, s.server, err = libhttp.NewServer(ctx,
@@ -235,7 +224,9 @@ func (s *HTTP) Addr() net.Addr {
// Shutdown the server // Shutdown the server
func (s *HTTP) Shutdown() error { func (s *HTTP) Shutdown() error {
return s.server.Shutdown() err := s.server.Shutdown()
s.provider.Shutdown()
return err
} }
// serveFavicon serves the remote's favicon.ico if it exists, otherwise // serveFavicon serves the remote's favicon.ico if it exists, otherwise
+113 -1
View File
@@ -22,6 +22,7 @@ import (
"github.com/rclone/rclone/fs/config/configmap" "github.com/rclone/rclone/fs/config/configmap"
"github.com/rclone/rclone/fs/config/obscure" "github.com/rclone/rclone/fs/config/obscure"
libcache "github.com/rclone/rclone/lib/cache" libcache "github.com/rclone/rclone/lib/cache"
libhttp "github.com/rclone/rclone/lib/http"
"github.com/rclone/rclone/vfs" "github.com/rclone/rclone/vfs"
"github.com/rclone/rclone/vfs/vfscommon" "github.com/rclone/rclone/vfs/vfscommon"
) )
@@ -161,13 +162,19 @@ type cacheEntry struct {
// //
// Any VFS are created with the vfsOpt passed in. // Any VFS are created with the vfsOpt passed in.
func New(ctx context.Context, opt *Options, vfsOpt *vfscommon.Options) *Proxy { func New(ctx context.Context, opt *Options, vfsOpt *vfscommon.Options) *Proxy {
return &Proxy{ p := &Proxy{
ctx: ctx, ctx: ctx,
Opt: *opt, Opt: *opt,
cmdLine: strings.Fields(opt.AuthProxy), cmdLine: strings.Fields(opt.AuthProxy),
vfsCache: libcache.New(), vfsCache: libcache.New(),
vfsOpt: *vfsOpt, vfsOpt: *vfsOpt,
} }
p.vfsCache.SetFinalizer(func(value any) {
if entry, ok := value.(cacheEntry); ok && entry.vfs != nil {
entry.vfs.Shutdown()
}
})
return p
} }
// run the proxy command returning a config map // run the proxy command returning a config map
@@ -374,3 +381,108 @@ func (p *Proxy) Get(key string) *vfs.VFS {
entry := value.(cacheEntry) entry := value.(cacheEntry)
return entry.vfs return entry.vfs
} }
// Shutdown shuts down all cached VFS instances
func (p *Proxy) Shutdown() {
if p != nil && p.vfsCache != nil {
p.vfsCache.Clear()
}
}
// Provider hands out VFS instances, either a fixed one or per-user via an auth proxy.
type Provider struct {
vfs *vfs.VFS // set if not using an auth proxy
proxy *Proxy // set if using an auth proxy
}
// NewProvider creates a Provider. If proxyOpt.AuthProxy is set it creates an
// auth proxy; otherwise it creates a fixed VFS from f and vfsOpt.
func NewProvider(ctx context.Context, f fs.Fs, vfsOpt *vfscommon.Options, proxyOpt *Options) *Provider {
p := &Provider{}
if proxyOpt != nil && proxyOpt.AuthProxy != "" {
p.proxy = New(ctx, proxyOpt, vfsOpt)
} else {
p.vfs = vfs.New(ctx, f, vfsOpt)
}
return p
}
// Get returns the VFS for the current request context.
// For fixed-VFS providers it returns the single VFS.
// For proxy providers it reads the VFS from the request's auth context.
func (p *Provider) Get(ctx context.Context) (*vfs.VFS, error) {
if p.vfs != nil {
return p.vfs, nil
}
value := libhttp.CtxGetAuth(ctx)
if value == nil {
return nil, errors.New("no VFS found in context")
}
VFS, ok := value.(*vfs.VFS)
if !ok {
return nil, fmt.Errorf("context value is not VFS: %#v", value)
}
return VFS, nil
}
// VFS returns the fixed VFS, or nil if using an auth proxy.
func (p *Provider) VFS() *vfs.VFS {
if p == nil {
return nil
}
return p.vfs
}
// Proxy returns the Proxy instance, or nil if not using an auth proxy.
func (p *Provider) Proxy() *Proxy {
if p == nil {
return nil
}
return p.proxy
}
// IsProxy returns true if using an auth proxy.
func (p *Provider) IsProxy() bool {
return p != nil && p.proxy != nil
}
// Shutdown tears down the provider: shuts down the fixed VFS or flushes all proxy cache entries.
func (p *Provider) Shutdown() {
if p == nil {
return
}
if p.vfs != nil {
p.vfs.Shutdown()
}
if p.proxy != nil {
p.proxy.Shutdown()
}
}
// Pin pins the cache entry for key so it won't be evicted by expire
func (p *Proxy) Pin(key string) {
if p != nil && p.vfsCache != nil {
p.vfsCache.Pin(key)
}
}
// Unpin unpins the cache entry for key
func (p *Proxy) Unpin(key string) {
if p != nil && p.vfsCache != nil {
p.vfsCache.Unpin(key)
}
}
// Pin pins the cache entry for key if using an auth proxy
func (p *Provider) Pin(key string) {
if p != nil && p.proxy != nil {
p.proxy.Pin(key)
}
}
// Unpin unpins the cache entry for key if using an auth proxy
func (p *Provider) Unpin(key string) {
if p != nil && p.proxy != nil {
p.proxy.Unpin(key)
}
}
+16 -15
View File
@@ -35,11 +35,10 @@ type Server struct {
server *httplib.Server server *httplib.Server
opt Options opt Options
f fs.Fs f fs.Fs
_vfs *vfs.VFS // don't use directly, use getVFS provider *proxy.Provider
faker *gofakes3.GoFakeS3 faker *gofakes3.GoFakeS3
backend *s3Backend backend *s3Backend
handler http.Handler handler http.Handler
proxy *proxy.Proxy
ctx context.Context // for global config ctx context.Context // for global config
s3Secret string s3Secret string
etagHashType hash.Type etagHashType hash.Type
@@ -51,8 +50,14 @@ func newServer(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Opt
f: f, f: f,
ctx: ctx, ctx: ctx,
opt: *opt, opt: *opt,
provider: proxy.NewProvider(ctx, f, vfsOpt, proxyOpt),
etagHashType: hash.None, etagHashType: hash.None,
} }
defer func() {
if err != nil {
w.provider.Shutdown()
}
}()
if w.opt.EtagHash == "auto" { if w.opt.EtagHash == "auto" {
w.etagHashType = f.Hashes().GetOne() w.etagHashType = f.Hashes().GetOne()
@@ -95,17 +100,12 @@ func newServer(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Opt
w.handler = w.faker.Server() w.handler = w.faker.Server()
if proxy.Opt.AuthProxy != "" { if w.provider.IsProxy() {
w.proxy = proxy.New(ctx, proxyOpt, vfsOpt)
// proxy auth middleware // proxy auth middleware
w.handler = proxyAuthMiddleware(w.handler, w) w.handler = proxyAuthMiddleware(w.handler, w)
w.handler = authPairMiddleware(w.handler, w) w.handler = authPairMiddleware(w.handler, w)
} else { } else if len(opt.AuthKey) > 0 {
w._vfs = vfs.New(ctx, f, vfsOpt) w.faker.AddAuthKeys(authList)
if len(opt.AuthKey) > 0 {
w.faker.AddAuthKeys(authList)
}
} }
w.server, err = httplib.NewServer(ctx, w.server, err = httplib.NewServer(ctx,
@@ -123,8 +123,8 @@ func newServer(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Opt
} }
func (w *Server) getVFS(ctx context.Context) (VFS *vfs.VFS, err error) { func (w *Server) getVFS(ctx context.Context) (VFS *vfs.VFS, err error) {
if w._vfs != nil { if w.provider.VFS() != nil {
return w._vfs, nil return w.provider.VFS(), nil
} }
value := ctx.Value(ctxKeyID) value := ctx.Value(ctxKeyID)
@@ -141,7 +141,7 @@ func (w *Server) getVFS(ctx context.Context) (VFS *vfs.VFS, err error) {
// auth does proxy authorization // auth does proxy authorization
func (w *Server) auth(r *http.Request, accessKeyID string) (value any, err error) { func (w *Server) auth(r *http.Request, accessKeyID string) (value any, err error) {
VFS, _, err := w.proxy.Call(stringToMd5Hash(accessKeyID), accessKeyID, false, r.RemoteAddr) VFS, _, err := w.provider.Proxy().Call(stringToMd5Hash(accessKeyID), accessKeyID, false, r.RemoteAddr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -168,8 +168,9 @@ func (w *Server) Addr() net.Addr {
// Shutdown the server // Shutdown the server
func (w *Server) Shutdown() error { func (w *Server) Shutdown() error {
w.backend.stopReaper() err := w.server.Shutdown()
return w.server.Shutdown() w.provider.Shutdown()
return err
} }
func authPairMiddleware(next http.Handler, ws *Server) http.Handler { func authPairMiddleware(next http.Handler, ws *Server) http.Handler {
+16 -19
View File
@@ -37,28 +37,24 @@ import (
type server struct { type server struct {
f fs.Fs f fs.Fs
opt Options opt Options
vfs *vfs.VFS provider *proxy.Provider
ctx context.Context // for global config ctx context.Context // for global config
config *ssh.ServerConfig config *ssh.ServerConfig
listener net.Listener listener net.Listener
stopped chan struct{} // for waiting on the listener to stop stopped chan struct{} // for waiting on the listener to stop
proxy *proxy.Proxy
} }
func newServer(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Options, proxyOpt *proxy.Options) (*server, error) { func newServer(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Options, proxyOpt *proxy.Options) (*server, error) {
s := &server{ s := &server{
f: f, f: f,
ctx: ctx, ctx: ctx,
opt: *opt, opt: *opt,
stopped: make(chan struct{}), provider: proxy.NewProvider(ctx, f, vfsOpt, proxyOpt),
} stopped: make(chan struct{}),
if proxy.Opt.AuthProxy != "" {
s.proxy = proxy.New(ctx, proxyOpt, vfsOpt)
} else {
s.vfs = vfs.New(ctx, f, vfsOpt)
} }
err := s.configure() err := s.configure()
if err != nil { if err != nil {
s.provider.Shutdown()
return nil, fmt.Errorf("sftp configuration failed: %w", err) return nil, fmt.Errorf("sftp configuration failed: %w", err)
} }
return s, nil return s, nil
@@ -66,8 +62,8 @@ func newServer(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Opt
// getVFS gets the vfs from s or the proxy // getVFS gets the vfs from s or the proxy
func (s *server) getVFS(what string, sshConn *ssh.ServerConn) (VFS *vfs.VFS) { func (s *server) getVFS(what string, sshConn *ssh.ServerConn) (VFS *vfs.VFS) {
if s.proxy == nil { if !s.provider.IsProxy() {
return s.vfs return s.provider.VFS()
} }
if sshConn.Permissions == nil || sshConn.Permissions.Extensions == nil { if sshConn.Permissions == nil || sshConn.Permissions.Extensions == nil {
fs.Infof(what, "SSH Permissions Extensions not found") fs.Infof(what, "SSH Permissions Extensions not found")
@@ -78,7 +74,7 @@ func (s *server) getVFS(what string, sshConn *ssh.ServerConn) (VFS *vfs.VFS) {
fs.Infof(what, "VFS key not found") fs.Infof(what, "VFS key not found")
return nil return nil
} }
VFS = s.proxy.Get(key) VFS = s.provider.Proxy().Get(key)
if VFS == nil { if VFS == nil {
fs.Infof(what, "failed to read VFS from cache") fs.Infof(what, "failed to read VFS from cache")
return nil return nil
@@ -160,7 +156,7 @@ func (s *server) configure() (err error) {
fs.Logf(nil, "Loaded %d authorized keys from %q", len(authorizedKeysMap), authKeysFile) fs.Logf(nil, "Loaded %d authorized keys from %q", len(authorizedKeysMap), authKeysFile)
} }
if !s.opt.NoAuth && len(authorizedKeysMap) == 0 && s.opt.User == "" && s.opt.Pass == "" && s.proxy == nil { if !s.opt.NoAuth && len(authorizedKeysMap) == 0 && s.opt.User == "" && s.opt.Pass == "" && !s.provider.IsProxy() {
return errors.New("no authorization found, use --user/--pass or --authorized-keys or --no-auth or --auth-proxy") return errors.New("no authorization found, use --user/--pass or --authorized-keys or --no-auth or --auth-proxy")
} }
@@ -170,9 +166,9 @@ func (s *server) configure() (err error) {
ServerVersion: "SSH-2.0-" + fs.GetConfig(s.ctx).UserAgent, ServerVersion: "SSH-2.0-" + fs.GetConfig(s.ctx).UserAgent,
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
fs.Debugf(describeConn(c), "Password login attempt for %s", c.User()) fs.Debugf(describeConn(c), "Password login attempt for %s", c.User())
if s.proxy != nil { if s.provider.IsProxy() {
// query the proxy for the config // query the proxy for the config
_, vfsKey, err := s.proxy.Call(c.User(), string(pass), false, c.RemoteAddr().String()) _, vfsKey, err := s.provider.Proxy().Call(c.User(), string(pass), false, c.RemoteAddr().String())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -193,9 +189,9 @@ func (s *server) configure() (err error) {
}, },
PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) { PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) {
fs.Debugf(describeConn(c), "Public key login attempt for %s", c.User()) fs.Debugf(describeConn(c), "Public key login attempt for %s", c.User())
if s.proxy != nil { if s.provider.IsProxy() {
//query the proxy for the config //query the proxy for the config
_, vfsKey, err := s.proxy.Call( _, vfsKey, err := s.provider.Proxy().Call(
c.User(), c.User(),
base64.StdEncoding.EncodeToString(pubKey.Marshal()), base64.StdEncoding.EncodeToString(pubKey.Marshal()),
true, true,
@@ -327,6 +323,7 @@ func (s *server) Shutdown() error {
if errors.Is(err, io.ErrUnexpectedEOF) { if errors.Is(err, io.ErrUnexpectedEOF) {
err = nil err = nil
} }
s.provider.Shutdown()
s.Wait() s.Wait()
return err return err
} }
+15 -22
View File
@@ -4,7 +4,6 @@ package webdav
import ( import (
"context" "context"
"encoding/xml" "encoding/xml"
"errors"
"fmt" "fmt"
"mime" "mime"
"net" "net"
@@ -235,9 +234,8 @@ type WebDAV struct {
server *libhttp.Server server *libhttp.Server
opt Options opt Options
f fs.Fs f fs.Fs
_vfs *vfs.VFS // don't use directly, use getVFS provider *proxy.Provider
webdavhandler *webdav.Handler webdavhandler *webdav.Handler
proxy *proxy.Proxy
ctx context.Context // for global config ctx context.Context // for global config
etagHashType hash.Type etagHashType hash.Type
} }
@@ -265,8 +263,15 @@ func newWebDAV(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Opt
f: f, f: f,
ctx: ctx, ctx: ctx,
opt: *opt, opt: *opt,
provider: proxy.NewProvider(ctx, f, vfsOpt, proxyOpt),
etagHashType: hash.None, etagHashType: hash.None,
} }
defer func() {
if err != nil {
w.provider.Shutdown()
}
}()
if opt.EtagHash == "auto" { if opt.EtagHash == "auto" {
w.etagHashType = f.Hashes().GetOne() w.etagHashType = f.Hashes().GetOne()
} else if opt.EtagHash != "" { } else if opt.EtagHash != "" {
@@ -278,12 +283,9 @@ func newWebDAV(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Opt
if w.etagHashType != hash.None { if w.etagHashType != hash.None {
fs.Debugf(f, "Using hash %v for ETag", w.etagHashType) fs.Debugf(f, "Using hash %v for ETag", w.etagHashType)
} }
if proxyOpt.AuthProxy != "" {
w.proxy = proxy.New(ctx, proxyOpt, vfsOpt) if w.provider.IsProxy() {
// override auth
w.opt.Auth.CustomAuthFn = w.auth w.opt.Auth.CustomAuthFn = w.auth
} else {
w._vfs = vfs.New(ctx, f, vfsOpt)
} }
w.server, err = libhttp.NewServer(ctx, w.server, err = libhttp.NewServer(ctx,
@@ -335,23 +337,12 @@ func newWebDAV(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Opt
// Gets the VFS in use for this request // Gets the VFS in use for this request
func (w *WebDAV) getVFS(ctx context.Context) (VFS *vfs.VFS, err error) { func (w *WebDAV) getVFS(ctx context.Context) (VFS *vfs.VFS, err error) {
if w._vfs != nil { return w.provider.Get(ctx)
return w._vfs, nil
}
value := libhttp.CtxGetAuth(ctx)
if value == nil {
return nil, errors.New("no VFS found in context")
}
VFS, ok := value.(*vfs.VFS)
if !ok {
return nil, fmt.Errorf("context value is not VFS: %#v", value)
}
return VFS, nil
} }
// auth does proxy authorization // auth does proxy authorization
func (w *WebDAV) auth(r *http.Request, user, pass string) (value any, err error) { func (w *WebDAV) auth(r *http.Request, user, pass string) (value any, err error) {
VFS, _, err := w.proxy.Call(user, pass, false, r.RemoteAddr) VFS, _, err := w.provider.Proxy().Call(user, pass, false, r.RemoteAddr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -513,7 +504,9 @@ func (w *WebDAV) Addr() net.Addr {
// Shutdown the server // Shutdown the server
func (w *WebDAV) Shutdown() error { func (w *WebDAV) Shutdown() error {
return w.server.Shutdown() err := w.server.Shutdown()
w.provider.Shutdown()
return err
} }
// logRequest is called by the webdav module on every request // logRequest is called by the webdav module on every request