http: Add static file support

Static files are configured using a handful of config values. Static
files can be handled remotely or locally for prod or dev environments,
respectively.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2023-08-02 20:16:47 -07:00
parent d3e3d99b12
commit d79899ea87
5 changed files with 71 additions and 17 deletions

View File

@@ -1,5 +1,6 @@
from pathlib import Path
import os
from typing import Sequence
from dotenv import load_dotenv
@@ -19,8 +20,16 @@ def required(name: str) -> str:
return value
def default(name: str, default: str) -> str:
return os.getenv(name, default)
def default(name: str, default_value: str) -> str:
return os.getenv(name, default_value)
def one_of_default(name: str, values: Sequence[str], default_value: str) -> str:
value = default(name, default_value)
if value not in values:
required = ",".join(f'"{v}"' for v in values)
raise ConfigError(name, f"must be one of {required}; got {value} instead")
return value
THUMBS_DIR = Path(default("THUMBS_DIR", "thumbs"))
@@ -29,4 +38,11 @@ CACHE_DIR = Path(default("CACHE_DIR", "cache"))
DB_SQLITE3_PATH = Path(default("DB_SQLITE3_PATH", "bans.db"))
HTTP_DOMAIN = required("HTTP_DOMAIN")
HTTP_ROOT = default("HTTP_ROOT", r"/")
HTTP_ROOT = default("HTTP_ROOT", r"")
STATIC_HANDLER = one_of_default("STATIC_HANDLER", ("remote", "local"), "local")
STATIC_LOCAL_PATH = Path(default("STATIC_LOCAL_PATH", "static"))
STATIC_LOCAL_FOLLOW_SYMLINKS = one_of_default(
"STATIC_LOCAL_FOLLOW_SYMLINKS", ("yes", "true", "1", "no", "false", "0"), "true"
) in ("yes", "true", "1")
STATIC_ROOT = default("STATIC_ROOT", "/static")

View File

@@ -15,14 +15,15 @@ from .db import get_db, search_db
def route_url(url: str):
if url in ("/" or ""):
assert url == "" or url[0] == "/", "URL must be blank or start with a slash"
if url in ("", "/"):
return config.HTTP_ROOT
elif config.HTTP_ROOT in ("/" or ""):
return url
elif url.startswith("/"):
return f"{config.HTTP_ROOT}{url}"
else:
return f"{config.HTTP_ROOT}/{url}"
return f"{config.HTTP_ROOT}{url}"
def static_url(resource: str):
return f"{config.STATIC_ROOT}/{resource}"
_env = Environment(
@@ -32,6 +33,7 @@ _env = Environment(
_env.globals.update(
{
"route_url": route_url,
"static_url": static_url,
}
)
@@ -160,12 +162,23 @@ class IndexView(TemplateView):
app = web.Application()
app.add_routes(
[
web.get(route_url(r"/"), IndexView),
web.get(route_url(r"/faq"), template_view_factory("faq.html")),
web.get(route_url(r"/news"), template_view_factory("news.html")),
web.get(config.HTTP_ROOT, IndexView),
web.get(f"{config.HTTP_ROOT}/faq", template_view_factory("faq.html")),
web.get(f"{config.HTTP_ROOT}/news", template_view_factory("news.html")),
]
)
if config.STATIC_HANDLER == "local":
app.add_routes(
[
web.static(
config.STATIC_ROOT,
config.STATIC_LOCAL_PATH,
follow_symlinks=config.STATIC_LOCAL_FOLLOW_SYMLINKS,
)
]
)
def run_app():
web.run_app(app)

View File

@@ -22,8 +22,10 @@ body {
}
nav {
/*
position: fixed;
top: 0;
*/
width: 100%;
margin: 5px 0;
text-align: left;
@@ -155,6 +157,9 @@ table tr {
{% endblock style %}
</head>
<body>
<nav>
[ <a href="{{route_url("/")}}">Home</a> / <a href="{{route_url("/news")}}">News</a> / <a href="{{route_url("/faq")}}">FAQ</a> ]
</nav>
{% block body %}
<header>
{% block header %}
@@ -172,9 +177,6 @@ table tr {
</div>
{% endblock header %}
</header>
<nav>
[ <a href="{{route_url("/")}}">Home</a> / <a href="{{route_url("/news")}}">News</a> / <a href="{{route_url("/faq")}}">FAQ</a> ]
</nav>
<main>
{% block main %}
{% endblock main %}

View File

@@ -50,7 +50,7 @@
</span>
</div>
<span class="file-thumb">
<img src="{{post['thumb_path']}}" data-md5="{{post['md5']}}" loading="lazy">
<img src="{{static_url(post['thumb_path'])}}" data-md5="{{post['md5']}}" loading="lazy">
</span>
</div>
{% endif %}

View File

@@ -7,9 +7,32 @@
# Sqlite3 database path. Defaults to "bans.db"
#DB_SQLITE3_PATH=bans.db
# Domain name of the server
# Domain name of the server. This is required.
HTTP_DOMAIN=domain.com
# Root of the HTTP server. Defaults to "/"
# If you host other things on your domain, you may want to update this to be "/bans" or something.
#HTTP_ROOT=/
# Static files handler. Defaults to "local"
# Valid values are:
# * local
# * remote
# Locally handled static files use the STATIC_LOCAL_PATH config value.
# IN GENERAL, the "local" configuration should not be used in a production environment.
#STATIC_HANDLER=local
# The local path to serve static files out of. Defaults to "static"
# This is only used when STATIC_HANDLER is set to "local".
#STATIC_LOCAL_PATH=static
# Whether to follow symlinks in the local static file handler. Defaults to "true"
# This is only used when STATIC_HANDLER is set to "local".
# Must be one of:
# * 1, true, yes
# * 0, false, no
#STATIC_LOCAL_FOLLOW_SYMLINKS=true
# This is the URL to map static files to. Defaults to /static
# This *WILL NOT* prepend the HTTP_ROOT path.
#STATIC_ROOT=/static