Open-Source Wikis

/

Caddy

/

Features

/

File server

caddyserver/caddy

File server

http.handlers.file_server serves static files from disk. Lives in modules/caddyhttp/fileserver/ (~30 KB across staticfiles.go).

Purpose

Take a request URI, map it to a path on disk under a configured root, and respond with the file contents — with proper Content-Type, conditional GETs, range requests, precompressed-asset support, and an optional HTML directory listing.

Directory layout

Path Role
modules/caddyhttp/fileserver/staticfiles.go The handler itself (~30 KB)
modules/caddyhttp/fileserver/browse.go Directory-listing rendering
modules/caddyhttp/fileserver/browse.html Embedded HTML template (~58 KB; includes CSS and JS)
modules/caddyhttp/fileserver/browsetplcontext.go Template context for browse.html
modules/caddyhttp/fileserver/matcher.go http.matchers.file — exists/doesn't-exist match
modules/caddyhttp/fileserver/caddyfile.go file_server directive parser
modules/caddyhttp/fileserver/command.go caddy file-server standalone subcommand
modules/caddyhttp/fileserver/testdata/ Fixtures used by the tests

Key abstractions

Type Where Description
FileServer staticfiles.go The handler module
Browse staticfiles.go Directory-listing config (sort key, sort direction, template path)
MatchFile matcher.go The file matcher — checks file existence on disk

How it works

graph TD
    Req[Request: /path/to/file.html] --> Handler[FileServer.ServeHTTP]
    Handler -->|join with root| Resolve[full filesystem path]
    Resolve --> Stat
    Stat -->|not found| Notfound[404 / pass-through]
    Stat -->|directory| Browse[browse.html / index.html]
    Stat -->|file| Cond[conditional GET checks]
    Cond -->|If-None-Match etc.| NotModified[304]
    Cond -->|range| Range[partial 206]
    Cond -->|full| Send[send body]
    Send --> Precompressed[try .gz/.br/.zst sibling]
    Precompressed --> Resp

Path resolution

  1. Take the URI path, strip any leading slash, join with root.
  2. Run it through filepath.Clean to defeat ../ traversal.
  3. Apply index_names (defaults: index.html, index.htm) when the resolved path is a directory.
  4. Apply try_files if configured (rewrites the URI to the first match — used for SPA fallbacks).

The filesystem is whatever caddy.Filesystems resolves; by default the OS filesystem, but a virtual filesystem (e.g. embedded files) can replace it via caddy.filesystems.*.

Range and conditional GETs

staticfiles.go uses http.ServeContent from the standard library, which handles If-Modified-Since, If-None-Match, Range, and If-Range correctly out of the box.

Precompressed assets

If the client signals Accept-Encoding: br and a sibling file index.html.br exists, the server serves the brotli file with an appropriate Content-Encoding header. This is registered via http.precompressed.* modules:

  • http.precompressed.gzip
  • http.precompressed.br
  • http.precompressed.zstd

Each is a tiny module that knows the file extension and the encoding name. staticfiles.go checks for them in the order configured.

Directory listing

If browse is enabled and the resolved path is a directory with no index file:

  • browsetplcontext.go builds a context (entries, sort, breadcrumb).
  • browse.html (embedded) renders. It is a single file that includes inline CSS and a small JS for sorting, search, and per-page state.

file matcher

matcher.go registers http.matchers.file. The matcher checks whether one of the listed files exists; with try_policy: first_exist, it returns the first hit and stores it in the replacer for downstream handlers (the canonical "Try files in this order" pattern, often used with php_fastcgi).

Standalone subcommand

command.go registers caddy file-server, which lets you run a quick file server from the CLI without writing a Caddyfile:

caddy file-server --listen :8080 --root ./public --browse

Integration points

  • HTTP app: standard handler.
  • Caddyfile: file_server directive (parsed by caddyfile.go).
  • try_files: uses the file matcher under the hood; it's a Caddyfile shorthand for setting up the matcher and a rewrite.

Entry points for modification

  • Change directory listing UX? Edit browse.html and browsetplcontext.go.
  • Add a precompressed encoding? Add a small module registering http.precompressed.<name>.
  • Tweak path-resolution rules? staticfiles.go: ServeHTTP.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

File server – Caddy wiki | Factory