http.files
import http.files
httplifts part of this module out to its own top level; each name below is shown with the path that reaches it. Anything still spelledhttp.files.*needsimport http.files.
Serving files off disk, with the parts that make it correct rather than merely working: conditional requests, entity tags, and byte ranges.
StaticFiles is the handler. ByteRange and the range parser implement
Range/206 Partial Content, which is what lets a browser seek within
a video without downloading it whole.
Functions
parse_range()
http.files.parse_range(header, size: number) -> ?list
Parses a Range header against a representation of size bytes.
Returns a list of ByteRange, an empty list when the header names only
ranges that fall outside the representation (a 416), or nil when the
header is not a byte range at all - which RFC 9110 §14.2 says to ignore
and answer with the whole thing.
Parameters
header(?string)size(number)
Returns ?list
weak_etag()
http.files.weak_etag(stats) -> string
A weak validator derived from a file’s size and modification time.
Weak rather than strong because two writes within the same second are
indistinguishable to it, which is exactly the condition RFC 9110 §8.8.1
reserves the W/ prefix for. It costs one stat, where a strong one
costs a full read of the file.
Parameters
stats(dict) — a file’sstats()dictionary
Returns string
etag_matches()
http.files.etag_matches(header, etag) -> bool
Whether an If-None-Match value matches etag.
Comparison is weak, per RFC 9110 §13.1.2: W/"x" and "x" match each
other, because a conditional GET only needs the two representations to
be equivalent, not byte-identical.
Parameters
header(string)etag(?string)
Returns bool
Classes
ByteRange
class http.ByteRange
One byte range asked for by a Range header, already resolved against
the size of the representation.
Fields
| Field | Type | Description |
|---|---|---|
start | number | The first byte of the range, inclusive. |
last | number | The last byte of the range, inclusive - as Content-Range states it, not as a length. |
Constructor
http.ByteRange(start, last)
ByteRange.length()
http.ByteRange.length() -> number
How many bytes the range covers.
Returns number
ByteRange.to_content_range()
http.ByteRange.to_content_range(total) -> string
The Content-Range field value for this range against a representation
of total bytes.
Parameters
total(number)
Returns string
StaticFiles
class http.StaticFiles
Serves files from a directory, with the conditional-request, range-request and caching behaviour a browser and a CDN both expect.
Every request path is percent-decoded and normalised before it is joined to the root, and the result is checked to still be inside the root afterwards - the decode-then-normalise-then-verify sequence, because doing any two of the three is not enough.
var files = http.StaticFiles('./public', { cache_age: 3600 })
server.handle('GET', '/static/' + '*path', @(request, response) {
files.serve(request, response, request.param('path'))
})
HttpServer.serve_files() wires all of that up for you; this class is
what it uses, and is here for applications that want to serve files from
somewhere the router does not reach.
Fields
| Field | Type | Description |
|---|---|---|
root | string | The directory files are served from, as an absolute path. |
index_files | list | Filenames tried when the request names a directory. |
cache_age | number | max-age, in seconds, for served files. |
etag | bool | Whether to send an ETag. |
precompressed | bool | Whether to answer a request for a file with a .gz or .br sibling by serving that instead, when the client… |
allow_dotfiles | bool | Whether to serve dotfiles. |
fallback | ?string | A file served in place of a missing one, relative to the root. |
Constructor
http.StaticFiles(directory: string, options: ?dict)
Parameters
directory(string)options(?dict) —index_files,cache_age,etag,precompressed,allow_dotfiles,fallback
Raises HttpError if the directory does not exist
StaticFiles.resolve()
http.StaticFiles.resolve(relative_path: string)
Resolves relative_path inside the root, or returns nil when it
escapes, names a dotfile that is not allowed, or does not exist.
Parameters
relative_path(string)
Returns — ?string: an absolute path
StaticFiles.serve()
http.StaticFiles.serve(request, response, relative_path: string)
Serves relative_path from the root into response.
Returns false when there is nothing to serve, leaving the response
untouched so the caller can fall through to its own not-found handling.
Parameters
request(HttpRequest)response(HttpResponse)relative_path(string)
Returns — bool: whether the response was filled in
2026, Richard Ore and Zuri contributors