.. _library_http_static_files:

``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 <../../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/4``
- ``serve/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``, and ``OPTIONS``
- ``200 OK`` file responses
- ``204 No Content`` ``OPTIONS`` responses with
  ``Allow: GET, HEAD, OPTIONS``
- canonical docroot-prefix checks after path normalization
- weak ``ETag`` and ``Last-Modified`` validators derived from file size
  and modification time
- ``412 Precondition Failed`` responses for failing ``If-Match`` and
  ``If-Unmodified-Since`` request preconditions
- ``304 Not Modified`` responses for matching ``If-None-Match`` and
  ``If-Modified-Since`` requests, with ``If-None-Match`` taking
  precedence
- single ``bytes=`` ranges with ``206 Partial Content``
- ``416 Range Not Satisfiable`` for malformed, unsupported multi-range,
  and unsatisfiable range requests
- ``If-Range`` fallback to full ``200 OK`` responses when the validator
  does not match or is only weakly equal
- ``406 Not Acceptable`` when ``Accept-Encoding`` rejects the identity
  representation and no acceptable precompressed variant is available
- ``404 Not Found`` for missing or unsafe paths
- custom fallback file responses for missing paths that resolve safely
  inside the document root
- ``405 Method Not Allowed`` for other methods with
  ``Allow: GET, HEAD, OPTIONS``
- ``301 Moved Permanently`` trailing-slash redirects for directory
  targets
- index-file lookup for directory targets
- optional directory-listing fallback for directory targets without an
  index file, using the ``http_directory_listing`` library
- precompressed ``.zst``, ``.br``, and ``.gz`` asset negotiation driven
  by ``Accept-Encoding``
- ``Vary: Accept-Encoding`` responses when negotiated precompressed
  variants exist
- MIME type and content-encoding guessing
- per-extension and per-path MIME type overrides on top of
  ``mime_types``
- optional CORS response decoration using the ``http_cors`` library
- configurable ``Cache-Control`` and ``Expires`` response headers, also
  shared by ``OPTIONS`` responses when configured
- configurable ``Content-Disposition`` response 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)`` where ``Directives`` is a list
  containing any of ``public``, ``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)``, or
  ``extension(Directive)``
- ``expires(none)`` to omit the header, ``expires(Seconds)`` for a
  relative expiry from the current system time, or
  ``expires(date_time(Year,Month,Day,Hour,Minute,Second))`` for an
  absolute expiry time
- ``mime_type_overrides(Overrides)`` where ``Overrides`` is a list
  containing ``extension(Extension, MediaType)`` or
  ``path(Path, MediaType)`` terms; path overrides match the served
  document-root relative file path and take precedence over extension
  overrides
- ``fallback_file(none)`` to omit custom fallback handling,
  ``fallback_file(not_found(Path))`` to serve a document-root relative
  file with ``404 Not Found`` status for missing targets, or
  ``fallback_file(spa(Path))`` to serve a document-root relative file
  with ``200 OK`` status for SPA client-side routes; fallback files are
  only considered after the requested path has resolved safely inside
  the document root
- ``directory_listing(false)`` to omit directory-listing fallback,
  ``directory_listing(true)`` to serve listings using the
  ``http_directory_listing`` defaults, or ``directory_listing(Options)``
  to pass options to ``http_directory_listing::serve/5``; listing
  fallback is only used for existing directory targets after
  trailing-slash redirect checks and index-file lookup, and before
  generic ``fallback_file/1`` handling
- ``cors([])`` to omit CORS response decoration, or ``cors(Policy)`` to
  decorate generated responses using
  ``http_cors::add_response_headers/4``; when the policy omits
  ``allowed_methods/1``, static files provide the default CORS method
  policy ``allowed_methods([get, head])``, and ``allowed_methods(any)``
  expands from the effective methods ``[get, head, options]``
- ``content_disposition(none)`` to omit the header,
  ``content_disposition(inline)`` or ``content_disposition(attachment)``
  for disposition-only values, and
  ``content_disposition(inline(Filename))`` or
  ``content_disposition(attachment(Filename))`` to include a quoted
  ``filename`` parameter

Current validator and date handling is intentionally conservative:

- ``ETag`` values are weak validators of the form
  ``W/"Size-ModifiedTime"``
- HTTP-date formatting, date validation, and Unix-time conversion
  delegate to the ``dates`` library; request parsing remains limited to
  the IMF-fixdate form generated for ``Last-Modified``
- ``If-Match`` entity-tag evaluation uses strong comparison semantics,
  so the generated weak ``ETag`` values only satisfy the wildcard ``*``
  precondition
- ``If-Range`` entity-tag evaluation uses strong comparison semantics,
  so the generated weak ``ETag`` values never authorize partial
  responses; matching ``Last-Modified`` dates can still do so
- ``If-Range`` mismatches fall back to the full ``200 OK`` response
  before range validation, so malformed or unsupported range syntax is
  ignored in that case
- precompressed-asset negotiation currently recognizes ``.zst``,
  ``.br``, and ``.gz`` sibling files and selects between them using
  ``Accept-Encoding`` quality values, otherwise falling back to the
  identity representation when it remains acceptable
- path sandboxing is based on canonicalized absolute-path prefix checks;
  no separate cross-backend symlink-policy layer has been added yet
