Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

http.files

import http.files

http lifts part of this module out to its own top level; each name below is shown with the path that reaches it. Anything still spelled http.files.* needs import 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’s stats() 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

FieldTypeDescription
startnumberThe first byte of the range, inclusive.
lastnumberThe 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

FieldTypeDescription
rootstringThe directory files are served from, as an absolute path.
index_fileslistFilenames tried when the request names a directory.
cache_agenumbermax-age, in seconds, for served files.
etagboolWhether to send an ETag.
precompressedboolWhether to answer a request for a file with a .gz or .br sibling by serving that instead, when the client…
allow_dotfilesboolWhether to serve dotfiles.
fallback?stringA 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