Serving docs statically via nginx

Add collect-static command to your app:

import shutil

import click
import flask

@app.cli.command("collect_static")
@click.argument(
    "destination_dir",
    nargs=1,
    type=click.Path(file_okay=False, dir_okay=True, writable=True, resolve_path=True),
    required=True,
)
def collect_static_command(destination_dir):
    docs.collect_static(destination_dir)
    shutil.copytree(
        flask.current_app.static_folder, destination_dir, dirs_exist_ok=True
    )
    click.echo(f"Static files collected into {destination_dir}.")

Configure nginx:

server {
    # ...

    location ^~ /v1/static {
        alias /home/user/static;
        try_files $uri $uri.html =404;
    }

    location ^~ /v1/docs {
        alias /home/user/static/docs;
        try_files $uri $uri.html =404;
    }

    # ...
}

Whenever deploying the app, call:

flask --app foobar_api collect-static /home/user/static

About Nginx and HTTP cache

You might be changing API docs rapidly and as a consequence, swagger.json changes rapidly too. There is a risk that other people will be looking at older version of docs - unless they hard reload their browser.

To avoid this, we should configure nginx to inject correct Cache-Control header into response for each served static files.

server {
    # ...

    location ^~ /v1/static {
        alias /home/user/static;
        try_files $uri $uri.html =404;

        add_header Cache-Control "public, max-age=86400, must-revalidate";
    }

    location ^~ /v1/docs {
        alias /home/user/static/docs;
        try_files $uri $uri.html =404;

        add_header Cache-Control "no-cache";
    }

    # ...
}

Above configuration assumes following:

  1. files under /home/user/static/ change rarely

    Browser is instructed to cache them for 1 day. After one day, browser WILL check with server if file had been modified. If server returns HTTP 304 Not Modified, file will not be re-downloaded.

    (via ETag - Nginx injects that automatically for us) and download new version of file only if it had changed.

  2. files under /v1/docs change more frequently

    Browser is instructed to cache these files, but to check with server if they had changed on every request. Again, this happens automatically via Etag that Nginx injects for us everywhere. If server returns HTTP 304 Not Modified, browser doesn’t need to re-download file. Otherwise, it re-downloads it.

There are a few mechanisms of comparing file contents between browser and server. Modern servers use Etag and Nginx injects that everywhere where it is needed. Details are usually not important if you are running somewhat modern system with Nginx.

For other web servers check their docs in combination with: