The HTTP Filesystem Protocol provides a RESTful interface for performing POSIX-like filesystem operations over HTTP. It enables hierarchical file and directory manipulation using standard HTTP methods with filesystem-specific metadata encoded in HTTP headers.
- RESTful Interface: HTTP methods map directly to filesystem operations
- Metadata in Headers: File attributes encoded as HTTP headers
- Path-based URLs: Filesystem paths map directly to URL paths
- Directory Listings: Directory contents encoded as plain text
- Atomic Operations: Individual operations are atomic
Filesystem paths map directly to HTTP URLs:
- Base URL:
https://example.com/fs - File path:
/path/to/file.txt→https://example.com/fs/path/to/file.txt - Directory path:
/path/to/dir→https://example.com/fs/path/to/dir
Note: Directory paths MAY end with / as a convenience to automatically set Content-Type: application/x-directory.
Retrieves file content or directory listing.
Request:
GET /path/to/file.txt HTTP/1.1Response (File):
HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Length: 1024
Content-Mode: 33188
Content-Modified: 1641024000
Content-Ownership: 1000:1000
[file content]Response (Directory):
HTTP/1.1 200 OK
Content-Type: application/x-directory
Content-Length: 45
Content-Mode: 16877
Content-Modified: 1641024000
Content-Ownership: 1000:1000
file.txt 33188
subdir 16877Retrieves file/directory metadata without content.
Request:
HEAD /path/to/file.txt HTTP/1.1Response:
HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Length: 1024
Content-Mode: 33188
Content-Modified: 1641024000
Content-Ownership: 1000:1000Creates or completely replaces a file or directory.
Request (File):
PUT /path/to/file.txt HTTP/1.1
Content-Type: application/octet-stream
Content-Length: 12
Content-Mode: 33188
Content-Modified: 1641024000
Content-Ownership: 1000:1000
Hello World!Request (Directory):
PUT /path/to/dir HTTP/1.1
Content-Type: application/x-directory
Content-Length: 0
Content-Mode: 16877
Content-Modified: 1641024000
Content-Ownership: 1000:1000
Alternative (using trailing slash convenience):
PUT /path/to/dir/ HTTP/1.1
Content-Length: 0
Content-Mode: 16877
Content-Modified: 1641024000
Content-Ownership: 1000:1000
Response:
HTTP/1.1 200 OK
OKUpdates file/directory metadata without changing content.
Request:
PATCH /path/to/file.txt HTTP/1.1
Content-Mode: 33261Response:
HTTP/1.1 200 OK
OKRemoves a file or directory.
Request:
DELETE /path/to/file.txt HTTP/1.1Response:
HTTP/1.1 200 OK
OK- Purpose: Unix file mode (permissions + type)
- Format: Decimal string representation of Unix mode
- Required: No (defaults applied)
- Examples:
33188- Regular file with 0644 permissions16877- Directory with 0755 permissions33261- Executable file with 0755 permissions
- Purpose: Last modification timestamp
- Format: Unix timestamp (seconds since epoch) as decimal string
- Required: No (current time used if omitted)
- Example:
1641024000
- Purpose: File owner and group
- Format:
uid:gidformat - Required: No (defaults to
0:0) - Example:
1000:1000
- Purpose: MIME type indicator
- Values:
application/x-directory- Directoryapplication/octet-stream- Binary file (default)- Other standard MIME types as appropriate
- Required: No (auto-detected from path and content)
- Purpose: Size of content in bytes
- Format: Decimal string
- Required: Yes for PUT requests
- Behavior: Standard HTTP header
Directory contents are encoded as plain text with the format:
filename mode
dirname mode
Characteristics:
- One entry per line
- Space-separated name and mode
- Lexicographically sorted
- Unix mode in decimal format
- Terminated with newline
Example:
.hidden 33188
README.md 33188
bin 16877
src 16877
- Primary: Content-Type header (
application/x-directory) - Secondary: Mode value (directory flag in Unix mode)
- Convenience: Path ending with
/automatically sets directory content-type
200 OK- Operation successful404 Not Found- File/directory does not exist405 Method Not Allowed- HTTP method not supported412 Precondition Failed- Conditional request failed
Error responses include plain text descriptions:
HTTP/1.1 404 Not Found
Object Not FoundHTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, PUT, PATCH, DELETE
Method Not AllowedReading Files:
- GET retrieves content with metadata in headers
- HEAD retrieves only metadata
- Returns 404 if file doesn't exist
Writing Files:
- PUT creates/replaces entire file
- All metadata must be provided to preserve existing values
- Content-Length header required
Modifying Files:
- PATCH updates metadata only, content unchanged
- Only provided headers are updated
- Existing metadata preserved if not specified
Reading Directories:
- GET returns directory listing as plain text
- Content-Type is
application/x-directory - Entries sorted lexicographically
Creating Directories:
- PUT with
Content-Type: application/x-directoryheader - Empty or minimal content body
- Alternatively, PUT with path ending in
/automatically sets directory content-type
Directory Maintenance:
- Server automatically maintains parent directory listings
- Adding/removing files updates parent directory
- PATCH with Content-Mode updates entry in parent listing
Standard HTTP conditional headers supported:
If-Match/If-None-MatchIf-Modified-Since/If-Unmodified-Since
Standard HTTP range requests supported for partial file reads:
Range: bytes=0-1023
- Protocol is transport-agnostic regarding authentication
- Implementations should use standard HTTP authentication
- Access control is implementation-specific
- Implementations should validate paths to prevent directory traversal
- Relative path components (
.,..) require careful handling - Path injection attacks should be prevented
- MUST support GET, HEAD, PUT, PATCH, DELETE methods
- MUST detect directories via
Content-Type: application/x-directory - SHOULD treat paths ending with
/as convenience for setting directory content-type - MUST maintain directory listings automatically
- SHOULD support conditional requests
- SHOULD validate metadata format
- MUST set
Content-Type: application/x-directoryfor directory operations - MAY use trailing
/on directory paths as convenience - MUST send required headers on PUT operations
- MUST parse directory listing format correctly
- SHOULD handle standard HTTP error responses
- SHOULD support conditional requests
- Metadata header names are case-insensitive (per HTTP)
- Directory listing format is strict (space-separated, sorted)
- Unix mode values are decimal integers
- Timestamps are Unix epoch seconds
PUT /documents/readme.txt HTTP/1.1
Content-Type: text/plain
Content-Length: 13
Content-Mode: 33188
Content-Ownership: 1000:1000
Hello, World!GET /documents HTTP/1.1
# Response:
readme.txt 33188
scripts 16877PATCH /documents/script.sh HTTP/1.1
Content-Mode: 33261HEAD /documents/config.json HTTP/1.1
# 200 = exists, 404 = doesn't exist- Extended attributes (xattrs) support
- Symbolic link operations
- File locking mechanisms
- Bulk operations
- Directory watching/notifications
- No atomic multi-file operations
- No recursive directory operations
- Access time not currently supported
- No built-in versioning or conflict resolution
Hey, this is cool, like a simpler webdav. I think I get why you wouldn't use it, but I do like how they make up their own HTTP methods like LOCK.
application/x-directorytext output a standard?PUT /foo/bar/baz.txt?POST /foo/bar/baz.txt?op=mv&dest=/new/loc.POST /foo/bar/baz.txt?lock=write&scope=shared&contact=URL-or-EMAILPOST /foo/bar?notify=URLorGET /foo/bar;changesfor a stream. But how do you structure the response without introducing a format? Maybe just send out[timestamp] [path] [mode]\nas changes happen?