http_static_files
The http_static_files library provides a router-agnostic helper for
serving existing files from a configured document root using normalized
http_core request and response terms.
This library resolves a relative request path against a document root,
canonicalizes the joined target path using os::absolute_file_name/2,
rejects canonicalized escapes with the same outward 404 Not Found
response used for missing files, falls back to configurable index files
for directory targets, guesses the response media type using
mime_types, emits ETag, Last-Modified, and Accept-Ranges
metadata, and returns file-backed response bodies that
http_server_core can stream efficiently.
API documentation
Open the ../../apis/library_index.html#http_static_files link in a web browser.
Loading
To load the library, load the loader.lgt file:
| ?- logtalk_load(http_static_files(loader)).
Testing
To test this library, load the tester.lgt file:
| ?- logtalk_load(http_static_files(tester)).
Current scope
The current library provides one public object with two public predicates:
serve/4serve/5
Supported options are:
index_files(IndexFiles)mime_types_strict(Boolean)mime_type_overrides(Overrides)fallback_file(Fallback)directory_listing(BooleanOrOptions)cors(Policy)cache_control(Directives)expires(Expires)content_disposition(Disposition)
Default options are:
index_files(['index.html', 'index.htm'])mime_types_strict(false)mime_type_overrides([])fallback_file(none)directory_listing(false)cors([])cache_control([])expires(none)content_disposition(none)
Supported features:
GET,HEAD, andOPTIONS200 OKfile responses204 No ContentOPTIONSresponses withAllow: GET, HEAD, OPTIONScanonical docroot-prefix checks after path normalization
weak
ETagandLast-Modifiedvalidators derived from file size and modification time412 Precondition Failedresponses for failingIf-MatchandIf-Unmodified-Sincerequest preconditions304 Not Modifiedresponses for matchingIf-None-MatchandIf-Modified-Sincerequests, withIf-None-Matchtaking precedencesingle
bytes=ranges with206 Partial Content416 Range Not Satisfiablefor malformed, unsupported multi-range, and unsatisfiable range requestsIf-Rangefallback to full200 OKresponses when the validator does not match or is only weakly equal406 Not AcceptablewhenAccept-Encodingrejects the identity representation and no acceptable precompressed variant is available404 Not Foundfor missing or unsafe pathscustom fallback file responses for missing paths that resolve safely inside the document root
405 Method Not Allowedfor other methods withAllow: GET, HEAD, OPTIONS301 Moved Permanentlytrailing-slash redirects for directory targetsindex-file lookup for directory targets
optional directory-listing fallback for directory targets without an index file, using the
http_directory_listinglibraryprecompressed
.zst,.br, and.gzasset negotiation driven byAccept-EncodingVary: Accept-Encodingresponses when negotiated precompressed variants existMIME type and content-encoding guessing
per-extension and per-path MIME type overrides on top of
mime_typesoptional CORS response decoration using the
http_corslibraryconfigurable
Cache-ControlandExpiresresponse headers, also shared byOPTIONSresponses when configuredconfigurable
Content-Dispositionresponse headers for inline or attachment file delivery
For directory listing, see the http_directory_listing library.
Cache-policy configuration uses these option values:
cache_control(Directives)whereDirectivesis a list containing any ofpublic,private,no_cache,no_store,no_transform,must_revalidate,proxy_revalidate,immutable,max_age(Seconds),s_maxage(Seconds),stale_while_revalidate(Seconds),stale_if_error(Seconds), orextension(Directive)expires(none)to omit the header,expires(Seconds)for a relative expiry from the current system time, orexpires(date_time(Year,Month,Day,Hour,Minute,Second))for an absolute expiry timemime_type_overrides(Overrides)whereOverridesis a list containingextension(Extension, MediaType)orpath(Path, MediaType)terms; path overrides match the served document-root relative file path and take precedence over extension overridesfallback_file(none)to omit custom fallback handling,fallback_file(not_found(Path))to serve a document-root relative file with404 Not Foundstatus for missing targets, orfallback_file(spa(Path))to serve a document-root relative file with200 OKstatus for SPA client-side routes; fallback files are only considered after the requested path has resolved safely inside the document rootdirectory_listing(false)to omit directory-listing fallback,directory_listing(true)to serve listings using thehttp_directory_listingdefaults, ordirectory_listing(Options)to pass options tohttp_directory_listing::serve/5; listing fallback is only used for existing directory targets after trailing-slash redirect checks and index-file lookup, and before genericfallback_file/1handlingcors([])to omit CORS response decoration, orcors(Policy)to decorate generated responses usinghttp_cors::add_response_headers/4; when the policy omitsallowed_methods/1, static files provide the default CORS method policyallowed_methods([get, head]), andallowed_methods(any)expands from the effective methods[get, head, options]content_disposition(none)to omit the header,content_disposition(inline)orcontent_disposition(attachment)for disposition-only values, andcontent_disposition(inline(Filename))orcontent_disposition(attachment(Filename))to include a quotedfilenameparameter
Current validator and date handling is intentionally conservative:
ETagvalues are weak validators of the formW/"Size-ModifiedTime"HTTP-date formatting, date validation, and Unix-time conversion delegate to the
dateslibrary; request parsing remains limited to the IMF-fixdate form generated forLast-ModifiedIf-Matchentity-tag evaluation uses strong comparison semantics, so the generated weakETagvalues only satisfy the wildcard*preconditionIf-Rangeentity-tag evaluation uses strong comparison semantics, so the generated weakETagvalues never authorize partial responses; matchingLast-Modifieddates can still do soIf-Rangemismatches fall back to the full200 OKresponse before range validation, so malformed or unsupported range syntax is ignored in that caseprecompressed-asset negotiation currently recognizes
.zst,.br, and.gzsibling files and selects between them usingAccept-Encodingquality values, otherwise falling back to the identity representation when it remains acceptablepath sandboxing is based on canonicalized absolute-path prefix checks; no separate cross-backend symlink-policy layer has been added yet