diff --git a/apps/node-agent/cmd/node-agent/app.go b/apps/node-agent/cmd/node-agent/app.go index 0ff0d6a..4e0b9e5 100644 --- a/apps/node-agent/cmd/node-agent/app.go +++ b/apps/node-agent/cmd/node-agent/app.go @@ -155,12 +155,13 @@ func (a *app) handler() http.Handler { for _, mount := range a.exportMounts { mountPathPrefix := strings.TrimSuffix(mount.mountPath, "/") + fs := webdav.Dir(mount.exportPath) dav := &webdav.Handler{ Prefix: mountPathPrefix, - FileSystem: webdav.Dir(mount.exportPath), + FileSystem: fs, LockSystem: webdav.NewMemLS(), } - mux.Handle(mount.mountPath, a.requireDAVAuth(mount, dav)) + mux.Handle(mount.mountPath, a.requireDAVAuth(mount, finderCompatible(dav, fs, mountPathPrefix))) } return mux diff --git a/apps/node-agent/cmd/node-agent/dav_finder.go b/apps/node-agent/cmd/node-agent/dav_finder.go new file mode 100644 index 0000000..399c0c9 --- /dev/null +++ b/apps/node-agent/cmd/node-agent/dav_finder.go @@ -0,0 +1,60 @@ +package main + +import ( + "context" + "net/http" + "os" + "strings" + + "golang.org/x/net/webdav" +) + +// finderCompatible wraps a webdav.Handler to work around macOS Finder quirks. +// +// Finder sends GET requests to WebDAV collection (directory) URLs and expects +// a 200 response. The standard Go webdav.Handler returns 405 Method Not Allowed +// for GET on directories, which causes Finder to refuse the mount. +// +// This wrapper intercepts GET and HEAD requests on directories and returns a +// minimal 200 response so Finder proceeds with the WebDAV protocol. +func finderCompatible(dav *webdav.Handler, fs webdav.FileSystem, prefix string) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet && r.Method != http.MethodHead { + dav.ServeHTTP(w, r) + return + } + + // Strip the prefix to get the filesystem-relative path. + fsPath := strings.TrimPrefix(r.URL.Path, prefix) + if fsPath == "" { + fsPath = "/" + } + + f, err := fs.OpenFile(context.Background(), fsPath, os.O_RDONLY, 0) + if err != nil { + // Not found or other error: let the regular handler deal with it. + dav.ServeHTTP(w, r) + return + } + defer f.Close() + + info, err := f.Stat() + if err != nil { + dav.ServeHTTP(w, r) + return + } + + if !info.IsDir() { + // Regular file: let the standard handler serve it. + dav.ServeHTTP(w, r) + return + } + + // Directory GET: return a minimal 200 so Finder is satisfied. + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.WriteHeader(http.StatusOK) + if r.Method == http.MethodGet { + _, _ = w.Write([]byte("
betterNAS WebDAV
\n")) + } + }) +}