[fastapi_vue] Further cleanup, wildcards for favicon.
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import fnmatch
|
||||||
import logging
|
import logging
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import time
|
import time
|
||||||
@@ -44,9 +45,9 @@ class Frontend:
|
|||||||
|
|
||||||
Features:
|
Features:
|
||||||
- Automatic zstd compression for compressible files
|
- Automatic zstd compression for compressible files
|
||||||
- ETag-based caching with configurable cache headers
|
- ETag-based caching of immutable assets
|
||||||
- SPA (Single Page Application) support
|
- SPA (Single Page Application) support
|
||||||
- Favicon handling from hashed assets
|
- /favicon.ico with correct MIME type (image/png etc)
|
||||||
- Dev mode: indexes files but returns error directing to Vite server
|
- Dev mode: indexes files but returns error directing to Vite server
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -54,7 +55,7 @@ class Frontend:
|
|||||||
index: Name of the index file (default: "index.html")
|
index: Name of the index file (default: "index.html")
|
||||||
spa: Enable SPA mode - serve index.html for unknown routes (default: False)
|
spa: Enable SPA mode - serve index.html for unknown routes (default: False)
|
||||||
cached: Path prefixes that are immutable (default: "/assets/")
|
cached: Path prefixes that are immutable (default: "/assets/")
|
||||||
favicon: E.g. /assets/logo.png will serve /assets/logo*.png as /favicon.ico
|
favicon: May use wildcards of full path. E.g. /assets/logo*.png matches logo.hash.png created by Vite
|
||||||
zstdlevel: Zstd compression level (default: 18)
|
zstdlevel: Zstd compression level (default: 18)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -142,15 +143,11 @@ class Frontend:
|
|||||||
zstd = None
|
zstd = None
|
||||||
www[name] = data, zstd, headers
|
www[name] = data, zstd, headers
|
||||||
if self.favicon:
|
if self.favicon:
|
||||||
p = PurePosixPath(self.favicon)
|
if m := fnmatch.filter(www, self.favicon):
|
||||||
base = str(p.with_suffix(""))
|
data, zstd, headers = www[m[0]]
|
||||||
ext = p.suffix
|
if "immutable" in headers.get("cache-control", ""):
|
||||||
hashed_path = next(
|
headers = {**headers, "cache-control": "max-age=86400"}
|
||||||
(path for path in www if path.startswith(base) and path.endswith(ext)),
|
www["/favicon.ico"] = data, zstd, headers
|
||||||
None,
|
|
||||||
)
|
|
||||||
if hashed_path:
|
|
||||||
www["/favicon.ico"] = www[hashed_path]
|
|
||||||
if not www:
|
if not www:
|
||||||
msg = "Frontend files missing, check your installation.\n"
|
msg = "Frontend files missing, check your installation.\n"
|
||||||
www["/"] = (
|
www["/"] = (
|
||||||
@@ -193,6 +190,8 @@ class Frontend:
|
|||||||
f"{self.base.name}: {len(self.www)} files in {1000 * duration:.1f} ms | "
|
f"{self.base.name}: {len(self.www)} files in {1000 * duration:.1f} ms | "
|
||||||
f"zstd {len(compfiles)} files {1e-6 * raw:.2f}->{1e-6 * comp:.2f} MB ({ratio:.0f} %)"
|
f"zstd {len(compfiles)} files {1e-6 * raw:.2f}->{1e-6 * comp:.2f} MB ({ratio:.0f} %)"
|
||||||
)
|
)
|
||||||
|
if self.favicon and "/favicon.ico" not in self.www:
|
||||||
|
logger.warning("Favicon not found: %s", self.favicon)
|
||||||
|
|
||||||
def route(self, app: FastAPI, mount_path="/"):
|
def route(self, app: FastAPI, mount_path="/"):
|
||||||
"""Register frontend routes with a FastAPI app.
|
"""Register frontend routes with a FastAPI app.
|
||||||
|
|||||||
Reference in New Issue
Block a user