The WebDAVService is a complete, production-ready HTTP file
service built on the Gumdrop framework. It serves static files from a
filesystem directory with high performance, and optionally provides full
WebDAV (RFC 2518) distributed authoring support. Because it is an
HTTP service, it can be configured with any
combination of HTTP/3, HTTP/2, and HTTP/1.1 listeners.
<service id="files" class="org.bluezoo.gumdrop.webdav.WebDAVService">
<property name="root-path">/var/www/html</property>
<property name="welcome-file">index.html</property>
<property name="allow-write">false</property>
<listener class="org.bluezoo.gumdrop.http.HTTPListener">
<property name="port">8080</property>
</listener>
</service>
Properties:
rootPath - filesystem directory to serve (required)welcomeFile - default file for directory requests (default:
index.html)allowWrite - enable PUT and DELETE methods (default:
false)The file server validates all paths to ensure they remain within the configured root directory. Symbolic links are resolved to their real paths before access checks. The root path must be a readable directory; if write operations are enabled, the server logs a warning if the directory is not writable.
File transfers use Java NIO's FileChannel.transferTo() where
possible, enabling zero-copy transfers directly from the filesystem to the
socket. This minimises memory allocation and CPU usage for large file
transfers.
For HTTP/3 and HTTP/2 connections, the file server benefits from stream multiplexing when serving mixed content (HTML, CSS, JavaScript, images).
To serve files over HTTP/3 as well as HTTP/2 and HTTP/1.1, add both an
HTTPListener and an HTTP3Listener:
<service id="files" class="org.bluezoo.gumdrop.webdav.WebDAVService">
<property name="root-path">/var/www/html</property>
<listener class="org.bluezoo.gumdrop.http.HTTPListener">
<property name="port">443</property>
<property name="secure">true</property>
<property name="keystore-file">keystore.p12</property>
<property name="keystore-pass">changeit</property>
</listener>
<listener class="org.bluezoo.gumdrop.http.h3.HTTP3Listener">
<property name="port">443</property>
<property name="cert-file">cert.pem</property>
<property name="key-file">key.pem</property>
</listener>
</service>
The service automatically advertises HTTP/3 availability via the
Alt-Svc response header on TCP connections.
The file server supports WebDAV (RFC 2518) distributed authoring when
enabled via the webdavEnabled property. This allows WebDAV
clients such as Windows Explorer, macOS Finder, or dedicated clients like
Cyberduck to access the file server as a network drive.
<service id="webdav" class="org.bluezoo.gumdrop.webdav.WebDAVService">
<property name="root-path">/var/www/dav</property>
<property name="allow-write">true</property>
<property name="webdav-enabled">true</property>
<listener class="org.bluezoo.gumdrop.http.HTTPListener">
<property name="port">8080</property>
</listener>
</service>
When WebDAV is enabled, the server advertises DAV: 1,2 in
OPTIONS responses and supports the following additional HTTP methods:
allprop, propname, or specific property requests.
The Depth header controls recursion (0, 1, or infinity).Destination header for the target URL. The
Overwrite header controls whether existing resources are
replaced (default: true). For collections, Depth controls
whether children are copied.Lock-Token header.The following live properties are computed from the filesystem and returned by PROPFIND requests:
creationdate - file creation time (ISO 8601 format)displayname - filenamegetcontentlength - file size in bytes (files only)getcontenttype - MIME typegetetag - entity tag for conditional requestsgetlastmodified - last modification time (HTTP date format)lockdiscovery - active locks on the resourceresourcetype - empty for files, <collection/>
for directoriessupportedlock - supported lock types (exclusive and shared
write locks)Dead (custom) properties are arbitrary name/value pairs stored on resources by WebDAV clients via PROPPATCH. Gumdrop persists dead properties using a dual-strategy backend:
user.webdav.. Properties travel with the file on copy/move
and are deleted automatically. Requires filesystem xattr support..webdav_filename and contain XML serialized with the
Gonzalez library. Sidecar I/O is fully non-blocking via
AsynchronousFileChannel.The dead property storage mode is configurable:
<service id="webdav" class="org.bluezoo.gumdrop.webdav.WebDAVService">
<property name="root-path">/var/www/dav</property>
<property name="allow-write">true</property>
<property name="webdav-enabled">true</property>
<property name="dead-property-storage">auto</property>
<listener class="org.bluezoo.gumdrop.http.HTTPListener">
<property name="port">8080</property>
</listener>
</service>
| Value | Behaviour |
|---|---|
auto | Use xattr when available, fall back to sidecar (default) |
xattr | Extended attributes only; fails if unsupported |
sidecar | Sidecar files only |
none | Dead properties disabled (PROPPATCH returns 403) |
Sidecar files are hidden from PROPFIND responses, HTML directory listings, and direct GET requests. They are automatically copied, moved, and deleted alongside their parent resource.
WebDAV locks prevent conflicting modifications when multiple clients access the same resource. Locks are:
When a resource is locked, modifying operations (PUT, DELETE, MOVE, PROPPATCH)
require a valid lock token in the If or Lock-Token
header.
DELETE on a collection (directory) recursively deletes all member resources
depth-first. If all deletions succeed, 204 No Content is returned.
If any individual deletion fails, a 207 Multi-Status response
lists the failed resources:
DELETE /documents/old-project/ HTTP/1.1
Host: example.com
HTTP/1.1 207 Multi-Status
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D="DAV:">
<D:response>
<D:href>/documents/old-project/locked-file.txt</D:href>
<D:status>HTTP/1.1 403 Forbidden</D:status>
</D:response>
</D:multistatus>
The If header supports the full grammar defined in RFC 4918 §10.4,
including tagged-list and no-tag-list syntax with ETag conditions and
Not negation. Multiple lists for the same resource are OR'd;
conditions within a list are AND'd.
// No-tag-list with lock token: If: (<opaquelocktoken:a1b2c3d4-...>) // Tagged-list for a specific resource: If: </documents/file.txt> (<opaquelocktoken:a1b2c3d4-...> ["etag-value"]) // Not condition (lock token must NOT be present): If: (Not <opaquelocktoken:old-token>) // Multiple conditions (OR'd): If: (<token-a>) (<token-b>)
PROPFIND /documents/ HTTP/1.1
Host: example.com
Depth: 1
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8"?>
<propfind xmlns="DAV:">
<prop>
<displayname/>
<getcontentlength/>
<getlastmodified/>
</prop>
</propfind>
Response (207 Multi-Status):
<?xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D="DAV:">
<D:response>
<D:href>/documents/</D:href>
<D:propstat>
<D:prop>
<D:displayname>documents</D:displayname>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
<D:response>
<D:href>/documents/report.pdf</D:href>
<D:propstat>
<D:prop>
<D:displayname>report.pdf</D:displayname>
<D:getcontentlength>245678</D:getcontentlength>
<D:getlastmodified>Tue, 06 Jan 2026 12:00:00 GMT</D:getlastmodified>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
</D:multistatus>
LOCK /documents/report.pdf HTTP/1.1 Host: example.com Timeout: Second-3600 Content-Type: application/xml <?xml version="1.0" encoding="utf-8"?> <lockinfo xmlns="DAV:"> <lockscope><exclusive/></lockscope> <locktype><write/></locktype> <owner>user@example.com</owner> </lockinfo>
Response includes the lock token:
HTTP/1.1 200 OK
Lock-Token: <opaquelocktoken:a1b2c3d4-e5f6-7890-abcd-ef1234567890>
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8"?>
<D:prop xmlns:D="DAV:">
<D:lockdiscovery>
<D:activelock>
<D:locktype><D:write/></D:locktype>
<D:lockscope><D:exclusive/></D:lockscope>
<D:depth>infinity</D:depth>
<D:owner>user@example.com</D:owner>
<D:timeout>Second-3600</D:timeout>
<D:locktoken>
<D:href>opaquelocktoken:a1b2c3d4-e5f6-7890-abcd-ef1234567890</D:href>
</D:locktoken>
</D:activelock>
</D:lockdiscovery>
</D:prop>
← Back to Main Page | HTTP Server & Client | Servlet Container | WebSocket Service & Client | FTP Server | Telemetry
Gumdrop File Server & WebDAV