index : static-web-server.git

ascending towards madness

author Jose Quintana <joseluisquintana20@gmail.com> 2022-02-04 21:13:33.0 +00:00:00
committer Jose Quintana <joseluisquintana20@gmail.com> 2022-02-04 21:13:33.0 +00:00:00
commit
a8360c476e87d9d76981b3235309a5bac6cc9c77 [patch]
tree
ec858af0e01e6a7185b7769350a396066b2b542b
parent
0c1a6c16e16ea4e476d6bade84d4c057e8ea3c6d
download
a8360c476e87d9d76981b3235309a5bac6cc9c77.tar.gz

docs: upcoming v2.5.0 [skip ci]



Diff

 README.md                                               |  2 +-
 docs/content/configuration/command-line-arguments.md    |  5 +-
 docs/content/configuration/environment-variables.md     |  3 +-
 docs/content/examples/basic-authentication.md           | 33 +---------
 docs/content/examples/cache-control-headers.md          | 41 +-----------
 docs/content/examples/compression.md                    | 44 +------------
 docs/content/examples/cors.md                           | 20 +-----
 docs/content/examples/directory-listing.md              | 66 +------------------
 docs/content/examples/docker.md                         | 56 +---------------
 docs/content/examples/error-pages.md                    | 18 +-----
 docs/content/examples/file-descriptor-socket-passing.md | 26 +-------
 docs/content/examples/http1.md                          | 16 +----
 docs/content/examples/http2-tls.md                      | 21 +------
 docs/content/examples/logging.md                        | 14 +----
 docs/content/examples/security-headers.md               | 17 +-----
 docs/content/examples/worker-threads.md                 | 35 +----------
 docs/content/features/basic-authentication.md           | 33 +++++++++-
 docs/content/features/cache-control-headers.md          | 41 +++++++++++-
 docs/content/features/compression.md                    | 44 ++++++++++++-
 docs/content/features/cors.md                           | 20 +++++-
 docs/content/features/directory-listing.md              | 66 ++++++++++++++++++-
 docs/content/features/docker.md                         | 56 +++++++++++++++-
 docs/content/features/error-pages.md                    | 18 +++++-
 docs/content/features/file-descriptor-socket-passing.md | 26 +++++++-
 docs/content/features/graceful-shutdown.md              | 28 ++++++++-
 docs/content/features/http1.md                          | 16 ++++-
 docs/content/features/http2-tls.md                      | 21 ++++++-
 docs/content/features/logging.md                        | 14 ++++-
 docs/content/features/security-headers.md               | 17 +++++-
 docs/content/features/worker-threads.md                 | 35 ++++++++++-
 docs/content/getting-started.md                         |  4 +-
 docs/content/index.md                                   |  2 +-
 docs/content/migration.md                               |  4 +-
 docs/mkdocs.yml                                         | 31 ++++----
 34 files changed, 464 insertions(+), 429 deletions(-)

diff --git a/README.md b/README.md
index 411652c..1aaded0 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,7 @@ It's cross-platform and available for `Linux`, `macOS`, `Windows` and `FreeBSD` 
- Compression on demand via [Accept-Encoding]https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding header.
- [Partial Content Delivery]https://en.wikipedia.org/wiki/Byte_serving support for byte-serving of large files.
- Optional [Cache Control]https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control headers for assets.
- [Termination signal]https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html handling with [graceful shutdown]https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-terminating-with-grace ability.
- [Termination signal]https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html handling with [graceful shutdown]https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-terminating-with-grace ability and grace period.
- [HTTP/2]https://tools.ietf.org/html/rfc7540 + TLS support.
- [Security headers]https://web.dev/security-headers/ for HTTP/2 by default.
- [HEAD]https://tools.ietf.org/html/rfc7231#section-4.3.2 responses.
diff --git a/docs/content/configuration/command-line-arguments.md b/docs/content/configuration/command-line-arguments.md
index 1bcae64..a48ff2c 100644
--- a/docs/content/configuration/command-line-arguments.md
+++ b/docs/content/configuration/command-line-arguments.md
@@ -10,7 +10,7 @@ The server can be configured via the following command-line arguments.
```
$ static-web-server -h

static-web-server 2.4.0
static-web-server 2.5.0
Jose Quintana <https://git.io/joseluisq>
A blazing fast and asynchronous web server for static files-serving.

@@ -49,6 +49,9 @@ OPTIONS:
            descriptor to be inherited by static-web-server. Cannot be used in conjunction with the port and host
            arguments. The included systemd unit file utilises this feature to increase security by allowing the static-
            web-server to be sandboxed more completely [env: SERVER_LISTEN_FD=]
    -q, --grace-period <grace-period>
            Defines a grace period in seconds after a `SIGTERM` signal is caught which will delay the server before to
            shut it down gracefully. The maximum value is 255 seconds [env: SERVER_GRACE_PERIOD=]  [default: 0]
    -a, --host <host>
            Host address (E.g 127.0.0.1 or ::1) [env: SERVER_HOST=]  [default: ::]

diff --git a/docs/content/configuration/environment-variables.md b/docs/content/configuration/environment-variables.md
index dad3f50..383eb41 100644
--- a/docs/content/configuration/environment-variables.md
+++ b/docs/content/configuration/environment-variables.md
@@ -18,6 +18,9 @@ Optional file descriptor number (e.g. `0`) to inherit an already-opened TCP list
### SERVER_ROOT
Relative or absolute root directory path of static files. Default `./public`.

### SERVER_GRACE_PERIOD
Defines a grace period in seconds after a `SIGTERM` signal is caught which will delay the server before to shut it down gracefully. The maximum value is `255` seconds. Default value is `0` (no delay).

### SERVER_LOG_LEVEL
Specify a logging level in lower case. Possible values are `error`, `warn`, `info`, `debug` or `trace`. Default `error`.

diff --git a/docs/content/examples/basic-authentication.md b/docs/content/examples/basic-authentication.md
deleted file mode 100644
index e103e2e..0000000
--- a/docs/content/examples/basic-authentication.md
+++ /dev/null
@@ -1,33 +0,0 @@
# Basic HTTP Authentication

**`SWS`** provides "Basic" HTTP Authentication Scheme using a `user-id/password` pairs encoded with `Base64`.

This feature is disabled by default and can be controlled by the string `--basic-auth` option or the equivalent [SERVER_BASIC_AUTH]./../configuration/environment-variables.md#server_basic_auth env.

First, create a `user-id/password` pair using your favourite tool.

!!! info "Note"
    Only the password must be encoded using the [`BCrypt`](https://en.wikipedia.org/wiki/Bcrypt) password-hashing function.

In this example we are using the Apache [`htpasswd`]https://httpd.apache.org/docs/2.4/programs/htpasswd.html tool.

```sh
htpasswd -nbBC5 "username" "password"
# username:$2y$05$KYOM0uaMQnEknnu/ckcCuuFyNQbc8BJEUk5X.ixtoCQpjXsc4geHK
```

!!! tip "Tip"
    The password verification happens at runtime but its verification speed depends on the computing time cost of `bcrypt` algorithm used.

    For example the `htpasswd` tool supports a `-C` argument in order to adjust the `bcrypt`'s computing time.
    
    Using a higher value is more secure but slower. The default values is `5` and the possible values are ranging from `4` to `17`.

Finally assign the credentails and run the server.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --basic-auth 'username:$2y$05$KYOM0uaMQnEknnu/ckcCuuFyNQbc8BJEUk5X.ixtoCQpjXsc4geHK'
```
diff --git a/docs/content/examples/cache-control-headers.md b/docs/content/examples/cache-control-headers.md
deleted file mode 100644
index 28f5be5..0000000
--- a/docs/content/examples/cache-control-headers.md
+++ /dev/null
@@ -1,41 +0,0 @@
# Cache Control Headers

**`SWS`** provides support for *arbitrary* [`Cache-Control`]https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control HTTP header specifying a `public` and `max-age` response directives.

This feature is enabled by default and can be controlled by the boolean `-e, --cache-control-headers` option or the equivalent [SERVER_CACHE_CONTROL_HEADERS]./../configuration/environment-variables.md#server_cache_control_headers env.

## Cache-Control Max-Age

Control headers are applied only to the following file types with the corresponding `max-age` values.

### One day

A `max-age` of *one day* duration is used by default.

!!! info "Note"
    One day `max-age` for example includes `html` and other file types.

### One hour

A `max-age` of *one hour* is applied only to the following file types.

```txt
atom, json, rss, xml
```

### One year

A `max-age` of *one year* is applied only to the following file types.

```txt
bmp, bz2, css, doc, gif, gz, htc, ico, jpeg, jpg, js, map, mjs, mp3, mp4, ogg, ogv, pdf, png, rar, rtf, tar, tgz, wav, weba, webm, webp, woff, woff2, zip
```

Below an example of how to enable the feature.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --cache-control-headers true
```
diff --git a/docs/content/examples/compression.md b/docs/content/examples/compression.md
deleted file mode 100644
index 070e98a..0000000
--- a/docs/content/examples/compression.md
+++ /dev/null
@@ -1,44 +0,0 @@
# Compression

**`SWS`** provides [`Gzip`]https://datatracker.ietf.org/doc/html/rfc1952, [`Deflate`]https://datatracker.ietf.org/doc/html/rfc1951#section-Abstract and [`Brotli`]https://www.ietf.org/rfc/rfc7932.txt compression of HTTP responses.

The compression functionality is determined by the [`Accept-Encoding`]https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding header and is only applied to text-based web file types only.

## MIME types compressed

Only this list of common text-based MIME type files will be compressed either with `Gzip`, `Deflate` or `Brotli` via the `Accept-Encoding` header value.

```txt
text/html
text/css
text/javascript
text/xml
text/plain
text/csv
text/calendar
text/markdown
text/x-yaml
text/x-toml
text/x-component
application/rtf
application/xhtml+xml
application/javascript
application/x-javascript
application/json
application/xml
application/rss+xml
application/atom+xml
application/vnd.ms-fontobject
font/truetype
font/opentype
image/svg+xml
```

This feature is enabled by default and can be controlled by the boolean `-x, --compression` option or the equivalent [SERVER_COMPRESSION]./../configuration/environment-variables.md#server_compression env.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --compression true
```
diff --git a/docs/content/examples/cors.md b/docs/content/examples/cors.md
deleted file mode 100644
index 787bfcd..0000000
--- a/docs/content/examples/cors.md
+++ /dev/null
@@ -1,20 +0,0 @@
# CORS

**`SWS`** provides optional [Cross-Origin Resource Sharing (CORS)]https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS support.

A list of allowed origin hosts (URLs) should be specified and separated by comas.
Or an asterisk (*) can be used in order to allow any host.

This feature is disabled by default and can be controlled by the string `-c, --cors-allow-origins` option or the equivalent [SERVER_CORS_ALLOW_ORIGINS]./../configuration/environment-variables.md#server_cors_allow_origins env.

Below an example of how to enable CORS.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --cors-allow-origins "https://domain.com"

    # Or use an asterisk to allow any host
    # --cors-allow-origins "*"
```
diff --git a/docs/content/examples/directory-listing.md b/docs/content/examples/directory-listing.md
deleted file mode 100644
index 6524346..0000000
--- a/docs/content/examples/directory-listing.md
+++ /dev/null
@@ -1,66 +0,0 @@
# Directory Listing

**`SWS`** provides a directory listing feature to display content of directories.

This feature is disabled by default and can be controlled by the boolean `-z, --directory-listing` option or the equivalent [SERVER_DIRECTORY_LISTING]./../configuration/environment-variables.md#server_directory_listing env.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --directory-listing true
```

And here an example of how the directory listing looks like.

<img title="SWS - Directory Listing" src="https://user-images.githubusercontent.com/1700322/145420578-5a508d2a-773b-4239-acc0-197ea2062ff4.png" width="400">

## Sorting

Sorting by `Name`, `Last modified` and `Size` is enabled as clickable columns when directory listing is activated via the `--directory-listing=true` option.

You can also use the `sort` query parameter to sort manually by certain attribute from URI. E.g `https://localhost/?sort=5`.

## Sorting by default

Some times one wants to sort by certain attribute but by **default**. In that case default ascending or descending ordering of files/dirs by their attributes is provided by the numeric `--directory-listing-order` option or the equivalent [SERVER_DIRECTORY_LISTING_ORDER]./../configuration/environment-variables.md#server_directory_listing_order env.

To do so you have to pass a [code sorting number]#code-numbers-for-sorting. E.g `--directory-listing-order=2`.

## Code numbers for sorting

Below the possible number code values for sorting/ordering which are grouped by attribute.

### Name

- `0`: Ascending
- `1`: Descending

### Last modified

- `2`: Ascending
- `3`: Descending

### Size

- `4`: Ascending
- `5`: Descending

### Default

- `6`: Unordered

!!! info "Tips"
    - The `--directory-listing-order` option depends on `--directory-listing` to be enabled.
    - Use the query `?sort=NUMBER` to customize the sorting. E.g `https://localhost/?sort=5` (sort by Size in descending order)

Example:

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --directory-listing true \
    # E.g Sorting file/dir names in descending order
    --directory-listing-order 1
```
diff --git a/docs/content/examples/docker.md b/docs/content/examples/docker.md
deleted file mode 100644
index 1a22b74..0000000
--- a/docs/content/examples/docker.md
+++ /dev/null
@@ -1,56 +0,0 @@
# Docker

`SWS` has first-class [Docker]https://docs.docker.com/get-started/overview/ support. It provides a [Scratch]https://hub.docker.com/_/scratch as well as the latest [Alpine Linux]https://hub.docker.com/_/alpine Docker images.

🐋 View on [Docker Hub]https://hub.docker.com/r/joseluisq/static-web-server/.

## Run a container

```sh
# Scratch image (just the binary)
docker run --rm -it -p 8787:80 joseluisq/static-web-server:2

# Or Alpine image
docker run --rm -it -p 8787:80 joseluisq/static-web-server:2-alpine
```

## Dockerfile

```Dockerfile
# Scratch image (just the binary)
FROM joseluisq/static-web-server:2

# Or Alpine image
FROM joseluisq/static-web-server:2-alpine
```

## Docker Compose

Below a [Docker Compose]https://docs.docker.com/compose/ example using the [Traefik Proxy]https://traefik.io/traefik/.

```yaml
version: "3.3"

services:
  web:
    image: joseluisq/static-web-server:2
    environment:
      # Note: those envs are customizable but also optional
      - SERVER_HOST=127.0.0.1
      - SERVER_PORT=80
      - SERVER_ROOT=/public
    volumes:
      - ./some-dir-path:/public
    labels:
      - "traefik.enable=true"
      - "traefik.frontend.entryPoints=https"
      - "traefik.backend=localhost_dev"
      - "traefik.frontend.rule=Host:localhost.dev"
      - "traefik.port=80"
    networks:
      - traefik_net

networks:
  traefik_net:
    external: true
```
diff --git a/docs/content/examples/error-pages.md b/docs/content/examples/error-pages.md
deleted file mode 100644
index 5c270da..0000000
--- a/docs/content/examples/error-pages.md
+++ /dev/null
@@ -1,18 +0,0 @@
# Error Pages

**`SWS`** provides custom HTML error pages for the HTTP `404` and `50x` status errors.

This feature is enabled by default and can be controlled either by the string `--page404` ([SERVER_ERROR_PAGE_404]./../configuration/environment-variables.md#server_error_page_404) or the `--page50x` ([SERVER_ERROR_PAGE_50X]./../configuration/environment-variables.md#server_error_page_50x) arguments.

!!! info "Tip"
    Either `--page404` and `--page50x` have defaults (optional values) so they can be specified or omitted as required.

Below an example of how to customize those HTML pages.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --page404 ./my-page-404.html \
    --page50x ./my-page-50x.html
```
diff --git a/docs/content/examples/file-descriptor-socket-passing.md b/docs/content/examples/file-descriptor-socket-passing.md
deleted file mode 100644
index d8e7860..0000000
--- a/docs/content/examples/file-descriptor-socket-passing.md
+++ /dev/null
@@ -1,26 +0,0 @@
# File Descriptor Socket Passing

**SWS** provides the ability to accept a socket listener as a file descriptor for use in sandboxing and on-demand applications via `systemd` (Linux), `launchd` (Macos) or similar.

!!! tip "Tip"
    The [Socket Activation](http://0pointer.de/blog/projects/socket-activation.html) model is basically an alternative to TCP port binding.

Socket activation is supported by the `-f, --fd` option or the equivalent [SERVER_LISTEN_FD]./../configuration/environment-variables.md#server_listen_fd env.

If you are using `inetd`, its "`wait`" option should be used in conjunction with static-web-server's `--fd 0`
option.

## Systemd

If you're using `systemd` on Linux, there is a fully working example in the SWS Git repository under the [.`/systemd`]https://github.com/joseluisq/static-web-server/tree/master/systemd directory.

## Testing

Alternatively, the light-weight [`systemfd`]https://github.com/mitsuhiko/systemfd utility may be
useful especially for testing purposes.

For example using `systemfd` utility as follow:

```sh
systemfd --no-pid -s http::8091 -- path/to/static-web-server --fd 0
```
diff --git a/docs/content/examples/http1.md b/docs/content/examples/http1.md
deleted file mode 100644
index a9b00d3..0000000
--- a/docs/content/examples/http1.md
+++ /dev/null
@@ -1,16 +0,0 @@
# HTTP/1

The HTTP/1 is the protocol by default and can be used specifying a host address via the `-a, --host` ([SERVER_HOST]./../configuration/environment-variables.md#server_host) argument, the port of the host via `-p, --port` ([SERVER_PORT]./../configuration/environment-variables.md#server_port) and the directory of the static files using the `-d, --root` ([SERVER_ROOT]./../configuration/environment-variables.md#server_root) argument.

!!! info "Tips"
    - Either `--host`, `--port` and `--root` have defaults (optional values) so they can be specified or omitted as required.
    - The server provides [Termination Signal](https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html) handling with [Graceful Shutdown](https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-terminating-with-grace) ability by default.

Below an example of how to run the server using HTTP/1.

```sh
static-web-server \
    --host 127.0.0.1 \
    --port 8787 \
    --root ./my-public-dir
```
diff --git a/docs/content/examples/http2-tls.md b/docs/content/examples/http2-tls.md
deleted file mode 100644
index 9eca939..0000000
--- a/docs/content/examples/http2-tls.md
+++ /dev/null
@@ -1,21 +0,0 @@
# HTTP/2 and TLS

**`SWS`** provides [HTTP/2]https://en.wikipedia.org/wiki/HTTP/2 protocol and [TLS]https://en.wikipedia.org/wiki/Transport_Layer_Security support.

This feature is disabled by default and can be activated via the boolean `-t, --http2` option as well as string arguments `--http2-tls-cert` (TLS certificate file path) and `--http2-tls-key` (private key file path).

!!! info "Tips"
    - Either `--host`, `--port` and `--root` have defaults (optional values) so they can be specified or omitted as required.
    - Don't forget to adjust the proper `--port` value for the HTTP/2 & TLS feature.
    - When this feature is enabled (`--http2=true`) then the [security headers](./security-headers.md) are also enabled automatically.
    - The server provides [Termination Signal](https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html) handling with [Graceful Shutdown](https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-terminating-with-grace) ability by default.

```sh
static-web-server \
    --host 127.0.0.1 \
    --port 8787 \
    --root ./my-public-dir \
    --http2 true \
    --http2-tls-cert ./my-tls.cert \
    --http2-tls-key ./my-tls.key
```
diff --git a/docs/content/examples/logging.md b/docs/content/examples/logging.md
deleted file mode 100644
index b4dfa88..0000000
--- a/docs/content/examples/logging.md
+++ /dev/null
@@ -1,14 +0,0 @@
# Logging

**`SWS`** provides logging support just specifying a log level in lower case. The values allowed are `error`, `warn`, `info`, `debug` and `trace`. The default value is `error`.

This feature is enabled by default and can be controlled by the string `-g, --log-level` option or the equivalent [SERVER_LOG_LEVEL]./../configuration/environment-variables.md#server_log_level env.

Below an example of how to adjust the log level.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --log-level "trace"
```
diff --git a/docs/content/examples/security-headers.md b/docs/content/examples/security-headers.md
deleted file mode 100644
index bcaf43a..0000000
--- a/docs/content/examples/security-headers.md
+++ /dev/null
@@ -1,17 +0,0 @@
# Security Headers

**`SWS`** provides several [security headers]https://web.dev/security-headers/ support.

When the [HTTP/2]../examples/http2-tls.md feature is activated *security headers* is enabled automatically.

This feature is disabled by default on HTTP/1 and can be controlled by the boolean `--security-headers` option or the equivalent [SERVER_SECURITY_HEADERS]./../configuration/environment-variables.md#server_security_headers env.

## Headers included

The following headers are only included.

- `Strict-Transport-Security: max-age=63072000; includeSubDomains; preload" (2 years max-age)`
- `X-Frame-Options: DENY`
- `X-XSS-Protection: 1; mode=block`
- `X-Content-Type-Options: nosniff`
- `Content-Security-Policy: frame-ancestors`
diff --git a/docs/content/examples/worker-threads.md b/docs/content/examples/worker-threads.md
deleted file mode 100644
index fe35071..0000000
--- a/docs/content/examples/worker-threads.md
+++ /dev/null
@@ -1,35 +0,0 @@
# Worker Threads Customization

**`SWS`** allows to customize the number of worker threads powered by the [Tokio]https://tokio.rs/ runtime.

This feature can be controlled by the numeric `-n, --threads-multiplier` option or the equivalent [SERVER_THREADS_MULTIPLIER]./../configuration/environment-variables.md#server_threads_multiplier env.

## Worker threads multiplier

The value of `-n, --threads-multiplier` works as multiplier digits in order to determine the number of worker threads used by the server.

Basically multipling this input number by the number of system CPUs.

The formula used is the following:

> worker threads = number of CPUs * n

*Where `n` is the input value of `-n, --threads-multiplier`.*

**For example:** If there are `4` available CPUs and the `--threads-multiplier` is `8` then the total of *worker threads* to use will be `32`.

!!! Info "Info"
    When the `--threads-multiplier` input value is `0` or `1` then one thread per core is used (default value).

!!! warn "Warn"
    Number of worker threads result should be a number between `1` and `32,768` though it is advised to keep this value on the smaller side. See [Tokio ` worker_threads` API](https://docs.rs/tokio/1.12.0/tokio/runtime/struct.Builder.html#method.worker_threads) for more details.

Below an example of how to adjust the number of worker threads.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    # NOTE: "8" gets multiplied by the number of the available cores.
    --threads-multiplier 8
```
diff --git a/docs/content/features/basic-authentication.md b/docs/content/features/basic-authentication.md
new file mode 100644
index 0000000..e103e2e
--- /dev/null
+++ b/docs/content/features/basic-authentication.md
@@ -0,0 +1,33 @@
# Basic HTTP Authentication

**`SWS`** provides "Basic" HTTP Authentication Scheme using a `user-id/password` pairs encoded with `Base64`.

This feature is disabled by default and can be controlled by the string `--basic-auth` option or the equivalent [SERVER_BASIC_AUTH]./../configuration/environment-variables.md#server_basic_auth env.

First, create a `user-id/password` pair using your favourite tool.

!!! info "Note"
    Only the password must be encoded using the [`BCrypt`](https://en.wikipedia.org/wiki/Bcrypt) password-hashing function.

In this example we are using the Apache [`htpasswd`]https://httpd.apache.org/docs/2.4/programs/htpasswd.html tool.

```sh
htpasswd -nbBC5 "username" "password"
# username:$2y$05$KYOM0uaMQnEknnu/ckcCuuFyNQbc8BJEUk5X.ixtoCQpjXsc4geHK
```

!!! tip "Tip"
    The password verification happens at runtime but its verification speed depends on the computing time cost of `bcrypt` algorithm used.

    For example the `htpasswd` tool supports a `-C` argument in order to adjust the `bcrypt`'s computing time.
    
    Using a higher value is more secure but slower. The default values is `5` and the possible values are ranging from `4` to `17`.

Finally assign the credentails and run the server.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --basic-auth 'username:$2y$05$KYOM0uaMQnEknnu/ckcCuuFyNQbc8BJEUk5X.ixtoCQpjXsc4geHK'
```
diff --git a/docs/content/features/cache-control-headers.md b/docs/content/features/cache-control-headers.md
new file mode 100644
index 0000000..28f5be5
--- /dev/null
+++ b/docs/content/features/cache-control-headers.md
@@ -0,0 +1,41 @@
# Cache Control Headers

**`SWS`** provides support for *arbitrary* [`Cache-Control`]https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control HTTP header specifying a `public` and `max-age` response directives.

This feature is enabled by default and can be controlled by the boolean `-e, --cache-control-headers` option or the equivalent [SERVER_CACHE_CONTROL_HEADERS]./../configuration/environment-variables.md#server_cache_control_headers env.

## Cache-Control Max-Age

Control headers are applied only to the following file types with the corresponding `max-age` values.

### One day

A `max-age` of *one day* duration is used by default.

!!! info "Note"
    One day `max-age` for example includes `html` and other file types.

### One hour

A `max-age` of *one hour* is applied only to the following file types.

```txt
atom, json, rss, xml
```

### One year

A `max-age` of *one year* is applied only to the following file types.

```txt
bmp, bz2, css, doc, gif, gz, htc, ico, jpeg, jpg, js, map, mjs, mp3, mp4, ogg, ogv, pdf, png, rar, rtf, tar, tgz, wav, weba, webm, webp, woff, woff2, zip
```

Below an example of how to enable the feature.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --cache-control-headers true
```
diff --git a/docs/content/features/compression.md b/docs/content/features/compression.md
new file mode 100644
index 0000000..070e98a
--- /dev/null
+++ b/docs/content/features/compression.md
@@ -0,0 +1,44 @@
# Compression

**`SWS`** provides [`Gzip`]https://datatracker.ietf.org/doc/html/rfc1952, [`Deflate`]https://datatracker.ietf.org/doc/html/rfc1951#section-Abstract and [`Brotli`]https://www.ietf.org/rfc/rfc7932.txt compression of HTTP responses.

The compression functionality is determined by the [`Accept-Encoding`]https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding header and is only applied to text-based web file types only.

## MIME types compressed

Only this list of common text-based MIME type files will be compressed either with `Gzip`, `Deflate` or `Brotli` via the `Accept-Encoding` header value.

```txt
text/html
text/css
text/javascript
text/xml
text/plain
text/csv
text/calendar
text/markdown
text/x-yaml
text/x-toml
text/x-component
application/rtf
application/xhtml+xml
application/javascript
application/x-javascript
application/json
application/xml
application/rss+xml
application/atom+xml
application/vnd.ms-fontobject
font/truetype
font/opentype
image/svg+xml
```

This feature is enabled by default and can be controlled by the boolean `-x, --compression` option or the equivalent [SERVER_COMPRESSION]./../configuration/environment-variables.md#server_compression env.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --compression true
```
diff --git a/docs/content/features/cors.md b/docs/content/features/cors.md
new file mode 100644
index 0000000..787bfcd
--- /dev/null
+++ b/docs/content/features/cors.md
@@ -0,0 +1,20 @@
# CORS

**`SWS`** provides optional [Cross-Origin Resource Sharing (CORS)]https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS support.

A list of allowed origin hosts (URLs) should be specified and separated by comas.
Or an asterisk (*) can be used in order to allow any host.

This feature is disabled by default and can be controlled by the string `-c, --cors-allow-origins` option or the equivalent [SERVER_CORS_ALLOW_ORIGINS]./../configuration/environment-variables.md#server_cors_allow_origins env.

Below an example of how to enable CORS.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --cors-allow-origins "https://domain.com"

    # Or use an asterisk to allow any host
    # --cors-allow-origins "*"
```
diff --git a/docs/content/features/directory-listing.md b/docs/content/features/directory-listing.md
new file mode 100644
index 0000000..6524346
--- /dev/null
+++ b/docs/content/features/directory-listing.md
@@ -0,0 +1,66 @@
# Directory Listing

**`SWS`** provides a directory listing feature to display content of directories.

This feature is disabled by default and can be controlled by the boolean `-z, --directory-listing` option or the equivalent [SERVER_DIRECTORY_LISTING]./../configuration/environment-variables.md#server_directory_listing env.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --directory-listing true
```

And here an example of how the directory listing looks like.

<img title="SWS - Directory Listing" src="https://user-images.githubusercontent.com/1700322/145420578-5a508d2a-773b-4239-acc0-197ea2062ff4.png" width="400">

## Sorting

Sorting by `Name`, `Last modified` and `Size` is enabled as clickable columns when directory listing is activated via the `--directory-listing=true` option.

You can also use the `sort` query parameter to sort manually by certain attribute from URI. E.g `https://localhost/?sort=5`.

## Sorting by default

Some times one wants to sort by certain attribute but by **default**. In that case default ascending or descending ordering of files/dirs by their attributes is provided by the numeric `--directory-listing-order` option or the equivalent [SERVER_DIRECTORY_LISTING_ORDER]./../configuration/environment-variables.md#server_directory_listing_order env.

To do so you have to pass a [code sorting number]#code-numbers-for-sorting. E.g `--directory-listing-order=2`.

## Code numbers for sorting

Below the possible number code values for sorting/ordering which are grouped by attribute.

### Name

- `0`: Ascending
- `1`: Descending

### Last modified

- `2`: Ascending
- `3`: Descending

### Size

- `4`: Ascending
- `5`: Descending

### Default

- `6`: Unordered

!!! info "Tips"
    - The `--directory-listing-order` option depends on `--directory-listing` to be enabled.
    - Use the query `?sort=NUMBER` to customize the sorting. E.g `https://localhost/?sort=5` (sort by Size in descending order)

Example:

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --directory-listing true \
    # E.g Sorting file/dir names in descending order
    --directory-listing-order 1
```
diff --git a/docs/content/features/docker.md b/docs/content/features/docker.md
new file mode 100644
index 0000000..1a22b74
--- /dev/null
+++ b/docs/content/features/docker.md
@@ -0,0 +1,56 @@
# Docker

`SWS` has first-class [Docker]https://docs.docker.com/get-started/overview/ support. It provides a [Scratch]https://hub.docker.com/_/scratch as well as the latest [Alpine Linux]https://hub.docker.com/_/alpine Docker images.

🐋 View on [Docker Hub]https://hub.docker.com/r/joseluisq/static-web-server/.

## Run a container

```sh
# Scratch image (just the binary)
docker run --rm -it -p 8787:80 joseluisq/static-web-server:2

# Or Alpine image
docker run --rm -it -p 8787:80 joseluisq/static-web-server:2-alpine
```

## Dockerfile

```Dockerfile
# Scratch image (just the binary)
FROM joseluisq/static-web-server:2

# Or Alpine image
FROM joseluisq/static-web-server:2-alpine
```

## Docker Compose

Below a [Docker Compose]https://docs.docker.com/compose/ example using the [Traefik Proxy]https://traefik.io/traefik/.

```yaml
version: "3.3"

services:
  web:
    image: joseluisq/static-web-server:2
    environment:
      # Note: those envs are customizable but also optional
      - SERVER_HOST=127.0.0.1
      - SERVER_PORT=80
      - SERVER_ROOT=/public
    volumes:
      - ./some-dir-path:/public
    labels:
      - "traefik.enable=true"
      - "traefik.frontend.entryPoints=https"
      - "traefik.backend=localhost_dev"
      - "traefik.frontend.rule=Host:localhost.dev"
      - "traefik.port=80"
    networks:
      - traefik_net

networks:
  traefik_net:
    external: true
```
diff --git a/docs/content/features/error-pages.md b/docs/content/features/error-pages.md
new file mode 100644
index 0000000..5c270da
--- /dev/null
+++ b/docs/content/features/error-pages.md
@@ -0,0 +1,18 @@
# Error Pages

**`SWS`** provides custom HTML error pages for the HTTP `404` and `50x` status errors.

This feature is enabled by default and can be controlled either by the string `--page404` ([SERVER_ERROR_PAGE_404]./../configuration/environment-variables.md#server_error_page_404) or the `--page50x` ([SERVER_ERROR_PAGE_50X]./../configuration/environment-variables.md#server_error_page_50x) arguments.

!!! info "Tip"
    Either `--page404` and `--page50x` have defaults (optional values) so they can be specified or omitted as required.

Below an example of how to customize those HTML pages.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --page404 ./my-page-404.html \
    --page50x ./my-page-50x.html
```
diff --git a/docs/content/features/file-descriptor-socket-passing.md b/docs/content/features/file-descriptor-socket-passing.md
new file mode 100644
index 0000000..d8e7860
--- /dev/null
+++ b/docs/content/features/file-descriptor-socket-passing.md
@@ -0,0 +1,26 @@
# File Descriptor Socket Passing

**SWS** provides the ability to accept a socket listener as a file descriptor for use in sandboxing and on-demand applications via `systemd` (Linux), `launchd` (Macos) or similar.

!!! tip "Tip"
    The [Socket Activation](http://0pointer.de/blog/projects/socket-activation.html) model is basically an alternative to TCP port binding.

Socket activation is supported by the `-f, --fd` option or the equivalent [SERVER_LISTEN_FD]./../configuration/environment-variables.md#server_listen_fd env.

If you are using `inetd`, its "`wait`" option should be used in conjunction with static-web-server's `--fd 0`
option.

## Systemd

If you're using `systemd` on Linux, there is a fully working example in the SWS Git repository under the [.`/systemd`]https://github.com/joseluisq/static-web-server/tree/master/systemd directory.

## Testing

Alternatively, the light-weight [`systemfd`]https://github.com/mitsuhiko/systemfd utility may be
useful especially for testing purposes.

For example using `systemfd` utility as follow:

```sh
systemfd --no-pid -s http::8091 -- path/to/static-web-server --fd 0
```
diff --git a/docs/content/features/graceful-shutdown.md b/docs/content/features/graceful-shutdown.md
new file mode 100644
index 0000000..d65be2a
--- /dev/null
+++ b/docs/content/features/graceful-shutdown.md
@@ -0,0 +1,28 @@
# Graceful Shutdown

**`SWS`** has the ability to terminate gracefully what is known as a [graceful shutdown]https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-terminating-with-grace process.

It means that when a `SIGTERM` [termination signal]https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html is caught the server will stop receiving more requests immediately but in turn it will continue processing all existing requests until they are completed (or closed).

!!! info "Notes"
    - In **BSD/Unix-like** systems, SWS will start the graceful shutdown process when a `SIGTERM`, `SIGINT` or `SIGQUIT` [termination signal](https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html) is caught.
    - In **Windows** systems otherwise, SWS will start the graceful shutdown process right after a <kbd>CTRL + C</kbd>. Which is used to abort the current task.

## Grace Period

Sometimes one wants to control the graceful shutdown process for different reasons. For example during [Kubernetes rollouts]https://github.com/joseluisq/static-web-server/issues/79.

In these situations, SWS allows to ***delay*** the graceful shutdown process right after a `SIGTERM` providing a grace period in seconds.

The feature is disabled by default and can be controlled by the numeric `-q, --grace-period` option or its equivalent [SERVER_GRACE_PERIOD]./../configuration/environment-variables.md#server_grace_period env.

!!! tip "Tip"
    The maximum grace period value is `255` seconds (4.25 min). Default value is `0` (no delay).

Here an example of delaying the graceful shutdown process by `10` seconds after a `SIGTERM`.

```sh
static-web-server -p 8787 -d ./public/ -g trace --grace-period 10
```


diff --git a/docs/content/features/http1.md b/docs/content/features/http1.md
new file mode 100644
index 0000000..a9b00d3
--- /dev/null
+++ b/docs/content/features/http1.md
@@ -0,0 +1,16 @@
# HTTP/1

The HTTP/1 is the protocol by default and can be used specifying a host address via the `-a, --host` ([SERVER_HOST]./../configuration/environment-variables.md#server_host) argument, the port of the host via `-p, --port` ([SERVER_PORT]./../configuration/environment-variables.md#server_port) and the directory of the static files using the `-d, --root` ([SERVER_ROOT]./../configuration/environment-variables.md#server_root) argument.

!!! info "Tips"
    - Either `--host`, `--port` and `--root` have defaults (optional values) so they can be specified or omitted as required.
    - The server provides [Termination Signal](https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html) handling with [Graceful Shutdown](https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-terminating-with-grace) ability by default.

Below an example of how to run the server using HTTP/1.

```sh
static-web-server \
    --host 127.0.0.1 \
    --port 8787 \
    --root ./my-public-dir
```
diff --git a/docs/content/features/http2-tls.md b/docs/content/features/http2-tls.md
new file mode 100644
index 0000000..9eca939
--- /dev/null
+++ b/docs/content/features/http2-tls.md
@@ -0,0 +1,21 @@
# HTTP/2 and TLS

**`SWS`** provides [HTTP/2]https://en.wikipedia.org/wiki/HTTP/2 protocol and [TLS]https://en.wikipedia.org/wiki/Transport_Layer_Security support.

This feature is disabled by default and can be activated via the boolean `-t, --http2` option as well as string arguments `--http2-tls-cert` (TLS certificate file path) and `--http2-tls-key` (private key file path).

!!! info "Tips"
    - Either `--host`, `--port` and `--root` have defaults (optional values) so they can be specified or omitted as required.
    - Don't forget to adjust the proper `--port` value for the HTTP/2 & TLS feature.
    - When this feature is enabled (`--http2=true`) then the [security headers](./security-headers.md) are also enabled automatically.
    - The server provides [Termination Signal](https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html) handling with [Graceful Shutdown](https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-terminating-with-grace) ability by default.

```sh
static-web-server \
    --host 127.0.0.1 \
    --port 8787 \
    --root ./my-public-dir \
    --http2 true \
    --http2-tls-cert ./my-tls.cert \
    --http2-tls-key ./my-tls.key
```
diff --git a/docs/content/features/logging.md b/docs/content/features/logging.md
new file mode 100644
index 0000000..b4dfa88
--- /dev/null
+++ b/docs/content/features/logging.md
@@ -0,0 +1,14 @@
# Logging

**`SWS`** provides logging support just specifying a log level in lower case. The values allowed are `error`, `warn`, `info`, `debug` and `trace`. The default value is `error`.

This feature is enabled by default and can be controlled by the string `-g, --log-level` option or the equivalent [SERVER_LOG_LEVEL]./../configuration/environment-variables.md#server_log_level env.

Below an example of how to adjust the log level.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    --log-level "trace"
```
diff --git a/docs/content/features/security-headers.md b/docs/content/features/security-headers.md
new file mode 100644
index 0000000..1a8e3b3
--- /dev/null
+++ b/docs/content/features/security-headers.md
@@ -0,0 +1,17 @@
# Security Headers

**`SWS`** provides several [security headers]https://web.dev/security-headers/ support.

When the [HTTP/2]../features/http2-tls.md feature is activated *security headers* is enabled automatically.

This feature is disabled by default on HTTP/1 and can be controlled by the boolean `--security-headers` option or the equivalent [SERVER_SECURITY_HEADERS]./../configuration/environment-variables.md#server_security_headers env.

## Headers included

The following headers are only included.

- `Strict-Transport-Security: max-age=63072000; includeSubDomains; preload" (2 years max-age)`
- `X-Frame-Options: DENY`
- `X-XSS-Protection: 1; mode=block`
- `X-Content-Type-Options: nosniff`
- `Content-Security-Policy: frame-ancestors`
diff --git a/docs/content/features/worker-threads.md b/docs/content/features/worker-threads.md
new file mode 100644
index 0000000..fe35071
--- /dev/null
+++ b/docs/content/features/worker-threads.md
@@ -0,0 +1,35 @@
# Worker Threads Customization

**`SWS`** allows to customize the number of worker threads powered by the [Tokio]https://tokio.rs/ runtime.

This feature can be controlled by the numeric `-n, --threads-multiplier` option or the equivalent [SERVER_THREADS_MULTIPLIER]./../configuration/environment-variables.md#server_threads_multiplier env.

## Worker threads multiplier

The value of `-n, --threads-multiplier` works as multiplier digits in order to determine the number of worker threads used by the server.

Basically multipling this input number by the number of system CPUs.

The formula used is the following:

> worker threads = number of CPUs * n

*Where `n` is the input value of `-n, --threads-multiplier`.*

**For example:** If there are `4` available CPUs and the `--threads-multiplier` is `8` then the total of *worker threads* to use will be `32`.

!!! Info "Info"
    When the `--threads-multiplier` input value is `0` or `1` then one thread per core is used (default value).

!!! warn "Warn"
    Number of worker threads result should be a number between `1` and `32,768` though it is advised to keep this value on the smaller side. See [Tokio ` worker_threads` API](https://docs.rs/tokio/1.12.0/tokio/runtime/struct.Builder.html#method.worker_threads) for more details.

Below an example of how to adjust the number of worker threads.

```sh
static-web-server \
    --port 8787 \
    --root ./my-public-dir \
    # NOTE: "8" gets multiplied by the number of the available cores.
    --threads-multiplier 8
```
diff --git a/docs/content/getting-started.md b/docs/content/getting-started.md
index ab057f6..03ce250 100644
--- a/docs/content/getting-started.md
+++ b/docs/content/getting-started.md
@@ -13,8 +13,8 @@ docker run --rm -it -p 8787:80 joseluisq/static-web-server:2
```

!!! info "Docker Tip"
    You can specify the Docker volume like `-v $HOME/my-public-dir:/public` in order to overwrite the default root directory. See [Docker examples](examples/docker.md) for more details.
    You can specify the Docker volume like `-v $HOME/my-public-dir:/public` in order to overwrite the default root directory. See [Docker examples](features/docker.md) for more details.

For more details about the available options type `static-web-server -h` or go to the [Command-line arguments]./configuration/command-line-arguments.md section.

Or if you are looking fo more advanced examples then have a look at [the examples]./examples/http1.md section.
Or if you are looking fo more advanced examples then have a look at [the features]./features/http1.md section.
diff --git a/docs/content/index.md b/docs/content/index.md
index b5c9938..6e49531 100644
--- a/docs/content/index.md
+++ b/docs/content/index.md
@@ -45,7 +45,7 @@ It's cross-platform and available for `Linux`, `macOS`, `Windows` and `FreeBSD` 
- Compression on demand via [Accept-Encoding]https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding header.
- [Partial Content Delivery]https://en.wikipedia.org/wiki/Byte_serving support for byte-serving of large files.
- Optional [Cache Control]https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control headers for assets.
- [Termination signal]https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html handling with [graceful shutdown]https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-terminating-with-grace ability.
- [Termination signal]https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html handling with [graceful shutdown]https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-terminating-with-grace ability and grace period.
- [HTTP/2]https://tools.ietf.org/html/rfc7540 + TLS support.
- [Security headers]https://web.dev/security-headers/ for HTTP/2 by default.
- [HEAD]https://tools.ietf.org/html/rfc7231#section-4.3.2 responses.
diff --git a/docs/content/migration.md b/docs/content/migration.md
index 441c040..716dcf8 100644
--- a/docs/content/migration.md
+++ b/docs/content/migration.md
@@ -16,7 +16,7 @@ This major `v2` has few breaking changes. However a migration should not represe
Please have in mind the following changes in `v2`:

- The server now supports only a root directory path (via `--root` or its equivalent env) so an assets path option is no longer required.
- Cache control headers are applied to assets in an arbitrary manner. See [control headers examples]./examples/cache-control-headers.md for more details.
- OpenSSL TLS for HTTP/1 is not longer supported instead for the HTTP/2 & TLS (via `--http2` option) the server uses [h2]https://github.com/hyperium/h2 which is on top of [Rustls]https://github.com/ctz/rustls. It means that instead of using a `.p12` or `.pfx` file you can now use only a certificate file along with its private key. See [HTTP/2 & TLS examples]./examples/http2-tls.md for more details.
- Cache control headers are applied to assets in an arbitrary manner. See [control headers examples]./features/cache-control-headers.md for more details.
- OpenSSL TLS for HTTP/1 is not longer supported instead for the HTTP/2 & TLS (via `--http2` option) the server uses [h2]https://github.com/hyperium/h2 which is on top of [Rustls]https://github.com/ctz/rustls. It means that instead of using a `.p12` or `.pfx` file you can now use only a certificate file along with its private key. See [HTTP/2 & TLS examples]./features/http2-tls.md for more details.

The rest of known options are equivalent to `v1` (except the new ones of course).
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index 83eaa52..42f768a 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -16,7 +16,7 @@ extra_css:
  - 'assets/style.css'

# Copyright
copyright: Copyright &copy; 2019-2021 Jose Quintana
copyright: Copyright &copy; 2019-2022 Jose Quintana

# Theme
theme:
@@ -118,20 +118,21 @@ nav:
  - 'Configuration':
    - 'Command Line Arguments': 'configuration/command-line-arguments.md'
    - 'Environment Variables': 'configuration/environment-variables.md'
  - 'Examples':
    - 'HTTP/1': 'examples/http1.md'
    - 'HTTP/2 and TLS': 'examples/http2-tls.md'
    - 'Logging': 'examples/logging.md'
    - 'Compression': 'examples/compression.md'
    - 'Cache Control Headers': 'examples/cache-control-headers.md'
    - 'CORS': 'examples/cors.md'
    - 'Security Headers': 'examples/security-headers.md'
    - 'Basic Authentication': 'examples/basic-authentication.md'
    - 'Directory Listing': 'examples/directory-listing.md'
    - 'Docker': 'examples/docker.md'
    - 'File Descriptor Socket Passing': './examples/file-descriptor-socket-passing.md'
    - 'Worker Threads Customization': 'examples/worker-threads.md'
    - 'Error Pages': 'examples/error-pages.md'
  - 'Features':
    - 'HTTP/1': 'features/http1.md'
    - 'HTTP/2 and TLS': 'features/http2-tls.md'
    - 'Logging': 'features/logging.md'
    - 'Compression': 'features/compression.md'
    - 'Cache Control Headers': 'features/cache-control-headers.md'
    - 'CORS': 'features/cors.md'
    - 'Security Headers': 'features/security-headers.md'
    - 'Basic Authentication': 'features/basic-authentication.md'
    - 'Directory Listing': 'features/directory-listing.md'
    - 'Docker': 'features/docker.md'
    - 'Graceful Shutdown': 'features/graceful-shutdown.md'
    - 'File Descriptor Socket Passing': './features/file-descriptor-socket-passing.md'
    - 'Worker Threads Customization': 'features/worker-threads.md'
    - 'Error Pages': 'features/error-pages.md'
  - 'Platforms & Architectures': 'platforms-architectures.md'
  - 'Migration from v1 to v2': 'migration.md'
  - 'Changelog v2 (latest stable)': 'https://github.com/joseluisq/static-web-server/blob/master/CHANGELOG.md'