webdavfs

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 12, 2025 License: MIT Imports: 15 Imported by: 0

README

webdavfs

Go Reference Go Report Card CI License

WebDAV filesystem implementation for the absfs ecosystem.

Overview

webdavfs provides bidirectional WebDAV support for the absfs ecosystem:

  1. Client Mode - Access remote WebDAV servers through the absfs.FileSystem interface
  2. Server Mode - Expose any absfs.FileSystem as a WebDAV server

This enables seamless integration with any WebDAV-compliant server (Nextcloud, ownCloud, Apache mod_dav, nginx, etc.) and allows serving any absfs filesystem (memfs, osfs, s3fs, unionfs, etc.) over WebDAV.

Quick Start

Client: Connect to a WebDAV Server
import "github.com/absfs/webdavfs"

// Connect to a WebDAV server
fs, err := webdavfs.New(&webdavfs.Config{
    URL:      "https://webdav.example.com/remote.php/dav/files/user/",
    Username: "user",
    Password: "password",
})
if err != nil {
    log.Fatal(err)
}
defer fs.Close()

// Use standard absfs operations
file, _ := fs.Open("/documents/report.txt")
Server: Serve an absfs Filesystem via WebDAV
import (
    "github.com/absfs/memfs"
    "github.com/absfs/webdavfs"
)

// Create any absfs.FileSystem
fs, _ := memfs.NewFS()

// Serve it via WebDAV
server := webdavfs.NewServer(fs, &webdavfs.ServerConfig{
    Prefix: "/webdav",
    Auth: &webdavfs.BasicAuth{
        Realm: "My Server",
        Validator: func(user, pass string) bool {
            return user == "admin" && pass == "secret"
        },
    },
})

http.ListenAndServe(":8080", server)

Client Mode (Detailed)

Architecture

Core Pattern: Direct Backend Integration

webdavfs follows the Direct Backend Integration pattern used by other absfs network filesystem implementations like sftpfs and s3fs. The implementation consists of:

  1. FileSystem struct - Holds WebDAV client connection and configuration
  2. File wrapper - Adapts WebDAV file operations to the absfs.File interface
  3. Protocol mapping - Translates absfs operations to WebDAV HTTP methods
┌─────────────────────┐
│  absfs Application  │
│  (uses absfs API)   │
└──────────┬──────────┘
           │ absfs.FileSystem interface
           ▼
┌─────────────────────┐
│    webdavfs         │
│  FileSystem struct  │
└──────────┬──────────┘
           │ WebDAV HTTP protocol
           ▼
┌─────────────────────┐
│  WebDAV Server      │
│  (remote storage)   │
└─────────────────────┘
absfs Interface Implementation

The package implements the complete absfs.FileSystem interface hierarchy:

Core Filer Interface (8 methods)
  • OpenFile(name string, flag int, perm os.FileMode) (File, error) → WebDAV GET/PUT/MKCOL
  • Mkdir(name string, perm os.FileMode) error → WebDAV MKCOL
  • Remove(name string) error → WebDAV DELETE
  • Rename(oldpath, newpath string) error → WebDAV MOVE
  • Stat(name string) (os.FileInfo, error) → WebDAV PROPFIND
  • Chmod(name string, mode os.FileMode) error → WebDAV PROPPATCH (limited support)
  • Chtimes(name string, atime, mtime time.Time) error → WebDAV PROPPATCH
  • Chown(name string, uid, gid int) error → WebDAV PROPPATCH (limited support)
Extended FileSystem Methods
  • Separator() → Returns '/'
  • ListSeparator() → Returns ':'
  • Chdir(dir string) error → Local state tracking
  • Getwd() (string, error) → Local state tracking
  • TempDir() string → Returns server-specific temp path
  • Open(name string) (File, error) → Convenience wrapper for OpenFile
  • Create(name string) (File, error) → Convenience wrapper for OpenFile
  • MkdirAll(name string, perm os.FileMode) error → Recursive MKCOL
  • RemoveAll(path string) error → Recursive DELETE
  • Truncate(name string, size int64) error → WebDAV partial PUT
File Interface Implementation

The File wrapper implements absfs.File (which extends io.Reader, io.Writer, io.Seeker, io.Closer):

Core Operations
  • Read(b []byte) (int, error) → HTTP GET with range
  • Write(b []byte) (int, error) → HTTP PUT with buffering
  • Close() error → Flush writes, close connection
  • Seek(offset int64, whence int) (int64, error) → Update position tracking
  • Stat() (os.FileInfo, error) → WebDAV PROPFIND
Extended Operations
  • ReadAt(b []byte, off int64) (int, error) → HTTP GET with Range header
  • WriteAt(b []byte, off int64) (int, error) → HTTP PUT with Content-Range
  • Readdir(n int) ([]os.FileInfo, error) → WebDAV PROPFIND with depth=1
  • Readdirnames(n int) ([]string, error) → Wrapper around Readdir
  • Truncate(size int64) error → WebDAV partial PUT
  • Sync() error → Flush buffered writes

WebDAV Protocol Mapping

HTTP Methods Used
absfs Operation WebDAV Method Description
Stat PROPFIND Get file/directory properties
Open (read) GET Download file content
Create/Write PUT Upload file content
Mkdir MKCOL Create directory
Remove DELETE Delete file/directory
Rename MOVE Rename/move resource
Chtimes PROPPATCH Modify modification time
Readdir PROPFIND (Depth: 1) List directory contents
WebDAV Properties Used

Standard DAV properties accessed via PROPFIND:

  • displayname → File name
  • getcontentlength → File size
  • getlastmodified → Modification time
  • resourcetype → File vs directory detection
  • getetag → Cache validation
  • getcontenttype → MIME type

Limitations and Considerations

WebDAV Server Variability

WebDAV is a loosely defined standard with varying server implementations:

  1. Permissions - Not all servers support Unix permissions via PROPPATCH

    • Chmod may be a no-op on some servers
    • Chown typically unsupported in most WebDAV servers
  2. Atomic Operations - Limited atomicity guarantees

    • No native locking in basic WebDAV (requires WebDAV Locking extension)
    • Concurrent writes may result in race conditions
  3. Performance - Network latency considerations

    • Each operation is an HTTP request
    • Directory listings can be expensive (recursive PROPFIND)
    • Consider using caching wrappers like corfs for read-heavy workloads
  4. Partial Updates - Server-dependent support

    • WriteAt and Truncate require Content-Range support
    • Some servers may require full file replacement
Security Considerations
  1. Authentication - Support for HTTP Basic, Digest, and Bearer tokens
  2. TLS/HTTPS - Strongly recommended for production use
  3. Credentials - Stored in memory, consider using credential helpers
  4. Path Traversal - All paths sanitized before HTTP requests

Usage Patterns

Standalone WebDAV Access
import "github.com/absfs/webdavfs"

// Connect to WebDAV server
fs, err := webdavfs.New(&webdavfs.Config{
    URL:      "https://webdav.example.com/remote.php/dav/files/user/",
    Username: "user",
    Password: "password",
})
if err != nil {
    log.Fatal(err)
}
defer fs.Close()

// Use standard absfs operations
file, err := fs.Create("documents/report.txt")
if err != nil {
    log.Fatal(err)
}
defer file.Close()

_, err = file.Write([]byte("Hello WebDAV!"))
Composition with Other absfs Filesystems
Cache-on-Read Pattern (using corfs)
import (
    "github.com/absfs/webdavfs"
    "github.com/absfs/corfs"
    "github.com/absfs/memfs"
)

// Remote WebDAV as primary
remote, _ := webdavfs.New(&webdavfs.Config{...})

// Local memory cache
cache := memfs.NewFS()

// Wrap with cache-on-read
fs := corfs.New(remote, cache)

// First read hits remote, subsequent reads use cache
data, _ := fs.ReadFile("large-file.bin")
Copy-on-Write Layering (using cowfs)
import (
    "github.com/absfs/webdavfs"
    "github.com/absfs/cowfs"
)

// WebDAV base layer (read-only in practice)
base, _ := webdavfs.New(&webdavfs.Config{...})

// Local overlay for writes
overlay := os.DirFS("/tmp/overlay")

// Writes go to overlay, reads fall through to WebDAV
fs := cowfs.New(overlay, base)

// Modify without affecting remote until explicit sync
fs.WriteFile("config.yml", data, 0644)
Multi-Protocol Access
import (
    "github.com/absfs/webdavfs"
    "github.com/absfs/sftpfs"
    "github.com/absfs/s3fs"
)

// Access same logical filesystem via different protocols
webdav, _ := webdavfs.New(&webdavfs.Config{URL: "https://..."})
sftp, _ := sftpfs.New(&sftpfs.Config{Host: "..."})
s3, _ := s3fs.New(&s3fs.Config{Bucket: "..."})

// Application code uses absfs.FileSystem interface
// Can switch between protocols transparently
var fs absfs.FileSystem = webdav

Implementation Structure

Expected package structure:

webdavfs/
├── README.md           # This file
├── FUZZING.md          # Fuzz testing documentation
├── go.mod              # Module definition
├── webdavfs.go         # FileSystem implementation
├── file.go             # File wrapper implementation
├── client.go           # WebDAV HTTP client
├── properties.go       # WebDAV property parsing
├── config.go           # Configuration structs
├── errors.go           # Error handling
├── webdavfs_test.go    # Integration tests
└── fuzz_test.go        # Fuzz tests
Key Components
webdavfs.go - FileSystem Implementation
type FileSystem struct {
    client *webdavClient
    root   string
    cwd    string
}

func New(config *Config) (*FileSystem, error)
func (fs *FileSystem) OpenFile(...) (absfs.File, error)
func (fs *FileSystem) Mkdir(...) error
// ... other Filer methods
file.go - File Wrapper
type File struct {
    fs       *FileSystem
    path     string
    mode     int
    offset   int64
    info     os.FileInfo
    buffer   *bytes.Buffer  // For write buffering
    modified bool
}

func (f *File) Read(b []byte) (int, error)
func (f *File) Write(b []byte) (int, error)
// ... other File methods
client.go - WebDAV HTTP Client
type webdavClient struct {
    httpClient *http.Client
    baseURL    *url.URL
    auth       authProvider
}

func (c *webdavClient) propfind(...) (*multistatus, error)
func (c *webdavClient) get(...) (io.ReadCloser, error)
func (c *webdavClient) put(...) error
func (c *webdavClient) mkcol(...) error
func (c *webdavClient) delete(...) error
func (c *webdavClient) move(...) error

Testing Strategy

Unit Tests
  • Mock HTTP server using httptest
  • Test each absfs method with various WebDAV responses
  • Error handling for malformed XML, network errors
  • Path sanitization and encoding
Fuzz Tests
  • Comprehensive fuzz testing for security and robustness
  • Tests XML parsing, path encoding, HTTP response handling, authentication headers, and property values
  • Helps discover edge cases and potential security vulnerabilities
  • See FUZZING.md for detailed documentation
Integration Tests
  • Real WebDAV server (docker container)
  • Full absfs compliance test suite
  • Concurrent access patterns
  • Large file handling
Compatibility Tests

Against common WebDAV servers:

  • Apache mod_dav
  • nginx with ngx_http_dav_module
  • Nextcloud
  • ownCloud
  • SabreDAV

Server Mode (Detailed)

The server functionality allows exposing any absfs.FileSystem as a WebDAV server. This is useful for:

  • Serving in-memory filesystems for testing
  • Creating WebDAV gateways to S3, SFTP, or other storage backends
  • Implementing virtual filesystems with WebDAV access
Server Architecture
┌─────────────────────┐
│   WebDAV Client     │
│  (any HTTP client)  │
└──────────┬──────────┘
           │ WebDAV HTTP protocol
           ▼
┌─────────────────────┐
│  webdavfs.Server    │
│  (HTTP handler)     │
└──────────┬──────────┘
           │ webdav.FileSystem interface
           ▼
┌─────────────────────┐
│ ServerFileSystem    │
│ (adapter)           │
└──────────┬──────────┘
           │ absfs.FileSystem interface
           ▼
┌─────────────────────┐
│  Any absfs FS       │
│  (memfs, osfs, etc) │
└─────────────────────┘
Server Configuration
type ServerConfig struct {
    // Prefix is the URL path prefix (e.g., "/webdav")
    Prefix string

    // Auth is an optional authentication provider
    Auth AuthProvider

    // Logger logs each request
    Logger func(r *http.Request, err error)

    // LockSystem for WebDAV locking (default: in-memory)
    LockSystem webdav.LockSystem
}
Authentication Options
Basic Authentication
server := webdavfs.NewServer(fs, &webdavfs.ServerConfig{
    Auth: &webdavfs.BasicAuth{
        Realm: "My WebDAV Server",
        Validator: func(username, password string) bool {
            return username == "admin" && password == "secret"
        },
    },
})
Bearer Token Authentication
server := webdavfs.NewServer(fs, &webdavfs.ServerConfig{
    Auth: &webdavfs.BearerAuth{
        Realm: "API",
        Validator: func(token string) bool {
            return token == "valid-api-token"
        },
    },
})
Custom Authentication

Implement the AuthProvider interface:

type AuthProvider interface {
    Authenticate(w http.ResponseWriter, r *http.Request) bool
}
Server Usage Examples
Serve a Union Filesystem
import (
    "github.com/absfs/memfs"
    "github.com/absfs/osfs"
    "github.com/absfs/unionfs"
    "github.com/absfs/webdavfs"
)

// Create layers
base, _ := osfs.NewFS()
overlay, _ := memfs.NewFS()

// Create union
ufs, _ := unionfs.New(overlay, base)

// Serve via WebDAV
server := webdavfs.NewServer(ufs, nil)
http.ListenAndServe(":8080", server)
Serve S3 via WebDAV
import (
    "github.com/absfs/s3fs"
    "github.com/absfs/webdavfs"
)

// Connect to S3
s3, _ := s3fs.New(&s3fs.Config{
    Bucket: "my-bucket",
    Region: "us-east-1",
})

// Serve S3 bucket via WebDAV
server := webdavfs.NewServer(s3, &webdavfs.ServerConfig{
    Prefix: "/s3",
})
http.ListenAndServe(":8080", server)
With Logging
server := webdavfs.NewServer(fs, &webdavfs.ServerConfig{
    Logger: func(r *http.Request, err error) {
        if err != nil {
            log.Printf("WebDAV ERROR %s %s: %v", r.Method, r.URL.Path, err)
        } else {
            log.Printf("WebDAV %s %s", r.Method, r.URL.Path)
        }
    },
})
WebDAV Methods Supported
HTTP Method WebDAV Operation Description
GET Download Download file content
PUT Upload Upload file content
DELETE Remove Delete file or directory
MKCOL Mkdir Create directory
COPY Copy Copy resource
MOVE Rename Move/rename resource
PROPFIND Stat/List Get properties or list directory
PROPPATCH SetProps Modify properties
LOCK Lock Lock resource (in-memory by default)
UNLOCK Unlock Unlock resource
OPTIONS Discover WebDAV capability discovery

absfs Ecosystem
  • absfs - Core filesystem abstraction
  • memfs - In-memory filesystem
  • osfs - OS filesystem wrapper
  • sftpfs - SFTP protocol access
  • s3fs - S3-compatible object storage
  • corfs - Cache-on-read wrapper
  • cowfs - Copy-on-write layers
  • unionfs - Union/overlay filesystem
WebDAV Libraries

Design Philosophy

This implementation follows absfs ecosystem principles:

  1. Interface Compliance - Full implementation of absfs.FileSystem
  2. Composition-Friendly - Works seamlessly with other absfs wrappers
  3. Minimal Dependencies - Only essential WebDAV protocol libraries
  4. Error Transparency - WebDAV errors wrapped in absfs error types
  5. Zero Configuration - Sensible defaults, minimal required config
  6. Test Coverage - Comprehensive tests against real servers

License

MIT License - see LICENSE file for details.

Contributing

Contributions welcome! Please ensure:

  • All absfs.FileSystem methods implemented
  • Tests pass against multiple WebDAV servers
  • Documentation updated for new features
  • Error handling follows absfs patterns

Documentation

Overview

Package webdavfs provides a WebDAV filesystem implementation for the absfs ecosystem.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewServerFileSystem

func NewServerFileSystem(fs absfs.FileSystem) webdav.FileSystem

NewServerFileSystem creates a new WebDAV filesystem adapter that wraps the given absfs.FileSystem. The returned webdav.FileSystem can be used with golang.org/x/net/webdav.Handler to serve files via WebDAV protocol.

Types

type AuthProvider

type AuthProvider interface {
	// Authenticate checks the request and returns true if authenticated.
	// It may modify the response (e.g., send 401) if authentication fails.
	Authenticate(w http.ResponseWriter, r *http.Request) bool
}

AuthProvider defines the interface for authentication.

type BasicAuth

type BasicAuth struct {
	// Realm is the authentication realm shown to the user.
	Realm string

	// Validator validates username/password combinations.
	// Returns true if valid, false otherwise.
	Validator func(username, password string) bool
}

BasicAuth implements HTTP Basic authentication.

func (*BasicAuth) Authenticate

func (b *BasicAuth) Authenticate(w http.ResponseWriter, r *http.Request) bool

Authenticate implements AuthProvider for HTTP Basic authentication.

type BearerAuth

type BearerAuth struct {
	// Realm is the authentication realm shown to the user.
	Realm string

	// Validator validates the bearer token.
	// Returns true if valid, false otherwise.
	Validator func(token string) bool
}

BearerAuth implements HTTP Bearer token authentication.

func (*BearerAuth) Authenticate

func (b *BearerAuth) Authenticate(w http.ResponseWriter, r *http.Request) bool

Authenticate implements AuthProvider for HTTP Bearer authentication.

type Config

type Config struct {
	// URL is the base URL of the WebDAV server (e.g., "https://webdav.example.com/remote.php/dav/files/user/")
	URL string

	// Username for HTTP authentication (optional)
	Username string

	// Password for HTTP authentication (optional)
	Password string

	// BearerToken for Bearer token authentication (optional, mutually exclusive with Username/Password)
	BearerToken string

	// HTTPClient allows customization of the HTTP client (optional)
	// If nil, a default client with reasonable timeouts will be used
	HTTPClient *http.Client

	// Timeout for HTTP requests (default: 30 seconds)
	Timeout time.Duration

	// TempDir specifies the temporary directory path on the WebDAV server (optional)
	// If empty, defaults to "/tmp"
	TempDir string
}

Config holds the configuration for connecting to a WebDAV server.

type ConfigError

type ConfigError struct {
	Field  string
	Reason string
}

ConfigError represents an error in the configuration

func (*ConfigError) Error

func (e *ConfigError) Error() string

type File

type File struct {
	// contains filtered or unexported fields
}

File represents an open file in the WebDAV filesystem

func (*File) Close

func (f *File) Close() error

Close closes the file

func (*File) Name

func (f *File) Name() string

Name returns the file name

func (*File) Read

func (f *File) Read(b []byte) (int, error)

Read reads data from the file

func (*File) ReadAt

func (f *File) ReadAt(b []byte, off int64) (int, error)

ReadAt reads from the file at a specific offset

func (*File) ReadDir

func (f *File) ReadDir(n int) ([]iofs.DirEntry, error)

ReadDir reads the contents of the directory and returns a slice of up to n DirEntry values in directory order. This is compatible with io/fs.ReadDirFile.

If n > 0, ReadDir returns at most n entries. In this case, if ReadDir returns an empty slice, it will return a non-nil error explaining why. At the end of a directory, the error is io.EOF.

If n <= 0, ReadDir returns all entries from the directory in a single slice. In this case, if ReadDir succeeds (reads all the way to the end of the directory), it returns the slice and a nil error.

func (*File) Readdir

func (f *File) Readdir(n int) ([]os.FileInfo, error)

Readdir reads directory contents

func (*File) Readdirnames

func (f *File) Readdirnames(n int) ([]string, error)

Readdirnames reads directory entry names

func (*File) Seek

func (f *File) Seek(offset int64, whence int) (int64, error)

Seek sets the offset for the next Read or Write

func (*File) Stat

func (f *File) Stat() (os.FileInfo, error)

Stat returns file information

func (*File) Sync

func (f *File) Sync() error

Sync flushes buffered writes

func (*File) Truncate

func (f *File) Truncate(size int64) error

Truncate changes the size of the file

func (*File) Write

func (f *File) Write(b []byte) (int, error)

Write writes data to the file

func (*File) WriteAt

func (f *File) WriteAt(b []byte, off int64) (int, error)

WriteAt writes to the file at a specific offset

func (*File) WriteString

func (f *File) WriteString(s string) (int, error)

WriteString writes a string to the file

type FileClosedError

type FileClosedError struct {
	Path string
}

FileClosedError is returned when an operation is attempted on a closed file

func (*FileClosedError) Error

func (e *FileClosedError) Error() string

type FileSystem

type FileSystem struct {
	// contains filtered or unexported fields
}

FileSystem implements the absfs.FileSystem interface for WebDAV servers

func New

func New(config *Config) (*FileSystem, error)

New creates a new WebDAV filesystem

func (*FileSystem) Chdir

func (fs *FileSystem) Chdir(dir string) error

Chdir changes the current working directory

func (*FileSystem) Chmod

func (fs *FileSystem) Chmod(name string, mode os.FileMode) error

Chmod changes file permissions (limited WebDAV support)

func (*FileSystem) Chown

func (fs *FileSystem) Chown(name string, uid, gid int) error

Chown changes file ownership (not supported by WebDAV)

func (*FileSystem) Chtimes

func (fs *FileSystem) Chtimes(name string, atime time.Time, mtime time.Time) error

Chtimes changes file modification time

func (*FileSystem) Close

func (fs *FileSystem) Close() error

Close closes the filesystem connection

func (*FileSystem) Create

func (fs *FileSystem) Create(name string) (absfs.File, error)

Create creates a new file for writing

func (*FileSystem) Getwd

func (fs *FileSystem) Getwd() (string, error)

Getwd returns the current working directory

func (*FileSystem) Mkdir

func (fs *FileSystem) Mkdir(name string, perm os.FileMode) error

Mkdir creates a directory

func (*FileSystem) MkdirAll

func (fs *FileSystem) MkdirAll(name string, perm os.FileMode) error

MkdirAll creates a directory and all parent directories

func (*FileSystem) Open

func (fs *FileSystem) Open(name string) (absfs.File, error)

Open opens a file for reading

func (*FileSystem) OpenFile

func (fs *FileSystem) OpenFile(name string, flag int, perm os.FileMode) (absfs.File, error)

OpenFile opens a file with the specified flags and permissions

func (*FileSystem) ReadDir

func (fs *FileSystem) ReadDir(name string) ([]iofs.DirEntry, error)

ReadDir reads the named directory and returns a list of directory entries sorted by filename. This is compatible with io/fs.ReadDirFS.

func (*FileSystem) ReadFile

func (fs *FileSystem) ReadFile(name string) ([]byte, error)

ReadFile reads the entire file and returns its contents. This method is compatible with io/fs.ReadFileFS.

func (*FileSystem) Remove

func (fs *FileSystem) Remove(name string) error

Remove removes a file or empty directory

func (*FileSystem) RemoveAll

func (fs *FileSystem) RemoveAll(name string) error

RemoveAll removes a path and all children

func (*FileSystem) Rename

func (fs *FileSystem) Rename(oldpath, newpath string) error

Rename renames (moves) a file or directory

func (*FileSystem) Stat

func (fs *FileSystem) Stat(name string) (os.FileInfo, error)

Stat returns file information

func (*FileSystem) Sub

func (fs *FileSystem) Sub(dir string) (iofs.FS, error)

Sub returns an fs.FS corresponding to the subtree rooted at dir. This is compatible with io/fs.SubFS.

func (*FileSystem) TempDir

func (fs *FileSystem) TempDir() string

TempDir returns the temporary directory path

func (*FileSystem) Truncate

func (fs *FileSystem) Truncate(name string, size int64) error

Truncate truncates a file to a specified size

func (*FileSystem) WriteFile

func (fs *FileSystem) WriteFile(name string, data []byte, perm os.FileMode) error

WriteFile writes data to a file

type InvalidSeekError

type InvalidSeekError struct {
	Offset int64
	Whence int
}

InvalidSeekError is returned when an invalid seek operation is attempted

func (*InvalidSeekError) Error

func (e *InvalidSeekError) Error() string

type MultiAuth

type MultiAuth struct {
	Providers []AuthProvider
}

MultiAuth combines multiple authentication providers. Authentication succeeds if any provider succeeds.

func (*MultiAuth) Authenticate

func (m *MultiAuth) Authenticate(w http.ResponseWriter, r *http.Request) bool

Authenticate implements AuthProvider by trying each provider in order. Returns true if any provider succeeds.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server provides a WebDAV server backed by any absfs.FileSystem. It implements http.Handler and can be used directly with http.ListenAndServe or integrated into existing HTTP routers.

func NewServer

func NewServer(fs absfs.FileSystem, config *ServerConfig) *Server

NewServer creates a new WebDAV server for the given filesystem.

Example usage:

fs, _ := memfs.NewFS()
server := webdavfs.NewServer(fs, &webdavfs.ServerConfig{
    Prefix: "/webdav",
    Auth: &webdavfs.BasicAuth{
        Realm: "My Server",
        Validator: func(user, pass string) bool {
            return user == "admin" && pass == "secret"
        },
    },
})
http.ListenAndServe(":8080", server)

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler returns the underlying http.Handler. Useful for wrapping with middleware.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler. It handles WebDAV protocol methods (PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK) as well as standard HTTP methods (GET, PUT, DELETE, OPTIONS).

func (*Server) SetAuth

func (s *Server) SetAuth(auth AuthProvider)

SetAuth updates the authentication provider.

func (*Server) SetLogger

func (s *Server) SetLogger(logger func(r *http.Request, err error))

SetLogger updates the request logger.

func (*Server) SetPrefix

func (s *Server) SetPrefix(prefix string)

SetPrefix updates the URL path prefix.

type ServerConfig

type ServerConfig struct {
	// Prefix is the URL path prefix to strip from WebDAV resource paths.
	// Example: "/webdav" means requests to "/webdav/file.txt" access "/file.txt"
	Prefix string

	// Auth is an optional authentication handler.
	// If nil, no authentication is required.
	Auth AuthProvider

	// Logger is an optional request logger function.
	// If nil, requests are not logged.
	Logger func(r *http.Request, err error)

	// LockSystem configures WebDAV locking behavior.
	// If nil, a MemLS (in-memory lock system) is used.
	LockSystem webdav.LockSystem
}

ServerConfig holds configuration for the WebDAV server.

type ServerFile

type ServerFile struct {
	// contains filtered or unexported fields
}

ServerFile adapts absfs.File to webdav.File. It wraps an absfs.File to provide the interface required by golang.org/x/net/webdav for serving files via WebDAV protocol.

func (*ServerFile) Close

func (f *ServerFile) Close() error

Close closes the file.

func (*ServerFile) Read

func (f *ServerFile) Read(p []byte) (int, error)

Read reads up to len(p) bytes into p.

func (*ServerFile) Readdir

func (f *ServerFile) Readdir(count int) ([]os.FileInfo, error)

Readdir reads the contents of the directory and returns a slice of os.FileInfo values, as would be returned by Stat, in directory order.

func (*ServerFile) Seek

func (f *ServerFile) Seek(offset int64, whence int) (int64, error)

Seek sets the offset for the next Read or Write.

func (*ServerFile) Stat

func (f *ServerFile) Stat() (os.FileInfo, error)

Stat returns the FileInfo structure describing the file.

func (*ServerFile) Write

func (f *ServerFile) Write(p []byte) (int, error)

Write writes len(p) bytes from p to the file.

type ServerFileSystem

type ServerFileSystem struct {
	// contains filtered or unexported fields
}

ServerFileSystem adapts absfs.FileSystem to webdav.FileSystem, allowing any absfs filesystem to be served via WebDAV.

func (*ServerFileSystem) Mkdir

func (s *ServerFileSystem) Mkdir(ctx context.Context, name string, perm os.FileMode) error

Mkdir creates a directory. The context parameter is accepted for interface compliance but not used.

func (*ServerFileSystem) OpenFile

func (s *ServerFileSystem) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error)

OpenFile opens a file with the specified flags and permissions. The context parameter is accepted for interface compliance but not used.

func (*ServerFileSystem) RemoveAll

func (s *ServerFileSystem) RemoveAll(ctx context.Context, name string) error

RemoveAll removes a file or directory tree. The context parameter is accepted for interface compliance but not used.

func (*ServerFileSystem) Rename

func (s *ServerFileSystem) Rename(ctx context.Context, oldName, newName string) error

Rename moves/renames a file or directory. The context parameter is accepted for interface compliance but not used.

func (*ServerFileSystem) Stat

func (s *ServerFileSystem) Stat(ctx context.Context, name string) (os.FileInfo, error)

Stat returns file information. The context parameter is accepted for interface compliance but not used.

type WebDAVError

type WebDAVError struct {
	StatusCode int
	Method     string
	Path       string
	Message    string
}

WebDAVError represents an error from the WebDAV server

func (*WebDAVError) Error

func (e *WebDAVError) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL