Fixed static files routes
This commit is contained in:
@@ -31,8 +31,16 @@ classifiers = [
|
|||||||
# Note: 'requirements.txt' is for development, this is for the package
|
# Note: 'requirements.txt' is for development, this is for the package
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"argon2-cffi",
|
||||||
|
"email-validator",
|
||||||
|
"httptools",
|
||||||
"myauth",
|
"myauth",
|
||||||
"myutils",
|
"myutils",
|
||||||
|
"python-fasthtml",
|
||||||
|
"PyYAML",
|
||||||
|
"uvloop",
|
||||||
|
"watchfiles",
|
||||||
|
"websockets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
@@ -62,5 +70,11 @@ dev = [
|
|||||||
# This section tells the build system where to find your package code
|
# This section tells the build system where to find your package code
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
[tool.setuptools]
|
[tool.setuptools]
|
||||||
package-dir = {"" = "src"}
|
package-dir = { "" = "src" }
|
||||||
packages = ["myfasthtml"]
|
packages = ["myfasthtml"]
|
||||||
|
|
||||||
|
[tool.setuptools.package-data]
|
||||||
|
myfasthtml = [
|
||||||
|
"assets/*.css",
|
||||||
|
"assets/*.js"
|
||||||
|
]
|
||||||
31
src/main.py
31
src/main.py
@@ -1,31 +0,0 @@
|
|||||||
from fasthtml import serve
|
|
||||||
from fasthtml.components import Link, Script
|
|
||||||
from fasthtml.fastapp import fast_app
|
|
||||||
from myauth import create_auth_app_for_sqlite
|
|
||||||
|
|
||||||
from myfasthtml.auth.routes import setup_auth_routes
|
|
||||||
from myfasthtml.auth.utils import create_auth_beforeware
|
|
||||||
|
|
||||||
beforeware = create_auth_beforeware()
|
|
||||||
# Create FastHTML app
|
|
||||||
daisyui_offline_links = [
|
|
||||||
Link(href="./myfasthtml/assets/daisyui-5.css", rel="stylesheet", type="text/css"),
|
|
||||||
Link(href="./myfasthtml/assets/daisyui-5-themes.css", rel="stylesheet", type="text/css"),
|
|
||||||
Script(src="./myfasthtml/assets/tailwindcss-browser@4.js"),
|
|
||||||
]
|
|
||||||
|
|
||||||
daisyui_online_links = [
|
|
||||||
Link(rel='stylesheet', href='https://cdn.jsdelivr.net/npm/daisyui@5/daisyui.css'),
|
|
||||||
Script(src='https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4'),
|
|
||||||
]
|
|
||||||
|
|
||||||
app, rt = fast_app(
|
|
||||||
before=beforeware,
|
|
||||||
hdrs=tuple(daisyui_offline_links)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Setup authentication routes
|
|
||||||
setup_auth_routes(app, rt)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
serve()
|
|
||||||
@@ -65,7 +65,7 @@ class LoginPage:
|
|||||||
cls="btn w-full font-bold py-2 px-4 rounded"
|
cls="btn w-full font-bold py-2 px-4 rounded"
|
||||||
),
|
),
|
||||||
|
|
||||||
action="/login-p",
|
action="/login",
|
||||||
method="post",
|
method="post",
|
||||||
cls="mb-6"
|
cls="mb-6"
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ class RegisterPage:
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
action="register-p",
|
action="register",
|
||||||
method="post",
|
method="post",
|
||||||
cls="mb-6"
|
cls="mb-6"
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ def setup_auth_routes(app, rt, mount_auth_app=True, sqlite_db_path="Users.db"):
|
|||||||
# PUBLIC ROUTES (Login & Register)
|
# PUBLIC ROUTES (Login & Register)
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
@rt("/login")
|
@rt("/login", methods=["GET"])
|
||||||
def get(error: str = None):
|
def get(error: str = None):
|
||||||
"""
|
"""
|
||||||
Display login page.
|
Display login page.
|
||||||
@@ -46,7 +46,7 @@ def setup_auth_routes(app, rt, mount_auth_app=True, sqlite_db_path="Users.db"):
|
|||||||
"""
|
"""
|
||||||
return LoginPage(error_message=error)
|
return LoginPage(error_message=error)
|
||||||
|
|
||||||
@rt("/login-p")
|
@rt("/login", methods=["POST"])
|
||||||
def post(email: str, password: str, session, redirect_url: str = "/"):
|
def post(email: str, password: str, session, redirect_url: str = "/"):
|
||||||
"""
|
"""
|
||||||
Handle login form submission.
|
Handle login form submission.
|
||||||
@@ -79,7 +79,7 @@ def setup_auth_routes(app, rt, mount_auth_app=True, sqlite_db_path="Users.db"):
|
|||||||
# Login failed - return error message via HTMX
|
# Login failed - return error message via HTMX
|
||||||
return LoginPage(error_message="Invalid email or password. Please try again.")
|
return LoginPage(error_message="Invalid email or password. Please try again.")
|
||||||
|
|
||||||
@rt("/register")
|
@rt("/register", methods=["GET"])
|
||||||
def get(error: str = None):
|
def get(error: str = None):
|
||||||
"""
|
"""
|
||||||
Display registration page.
|
Display registration page.
|
||||||
@@ -92,7 +92,7 @@ def setup_auth_routes(app, rt, mount_auth_app=True, sqlite_db_path="Users.db"):
|
|||||||
"""
|
"""
|
||||||
return RegisterPage(error_message=error)
|
return RegisterPage(error_message=error)
|
||||||
|
|
||||||
@rt("/register-p")
|
@rt("/register", methods=["POST"])
|
||||||
def post(email: str, username: str, password: str, confirm_password: str, session):
|
def post(email: str, username: str, password: str, confirm_password: str, session):
|
||||||
"""
|
"""
|
||||||
Handle registration form submission.
|
Handle registration form submission.
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ DEFAULT_SKIP_PATTERNS = [
|
|||||||
r'/static/.*',
|
r'/static/.*',
|
||||||
r'.*\.css',
|
r'.*\.css',
|
||||||
r'.*\.js',
|
r'.*\.js',
|
||||||
|
r'/myfasthtml/.*\.css',
|
||||||
|
r'/myfasthtml/.*\.js',
|
||||||
'/login',
|
'/login',
|
||||||
'/login-p',
|
|
||||||
'/register',
|
'/register',
|
||||||
'/register-p',
|
|
||||||
'/logout',
|
'/logout',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
82
src/myfasthtml/myfastapp.py
Normal file
82
src/myfasthtml/myfastapp.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
from importlib.resources import files
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Optional, Any
|
||||||
|
|
||||||
|
import fasthtml.fastapp
|
||||||
|
from fasthtml.components import Link, Script
|
||||||
|
from starlette.responses import Response
|
||||||
|
|
||||||
|
from myfasthtml.auth.routes import setup_auth_routes
|
||||||
|
|
||||||
|
|
||||||
|
def get_asset_path(filename):
|
||||||
|
"""Get asset file path"""
|
||||||
|
return files("myfasthtml") / "assets" / filename
|
||||||
|
|
||||||
|
|
||||||
|
# Get assets directory path
|
||||||
|
assets_path = files("myfasthtml") / "assets"
|
||||||
|
assets_dir = Path(str(assets_path))
|
||||||
|
|
||||||
|
|
||||||
|
def get_asset_content(filename):
|
||||||
|
"""Get asset file content"""
|
||||||
|
return get_asset_path(filename).read_text()
|
||||||
|
|
||||||
|
|
||||||
|
def create_app(daisyui: Optional[bool] = False, mount_auth_app: Optional[bool] = False, **kwargs) -> Any:
|
||||||
|
"""
|
||||||
|
Creates and configures a FastHtml application with optional support for daisyUI themes and
|
||||||
|
authentication routes.
|
||||||
|
|
||||||
|
:param daisyui: Flag to enable or disable inclusion of daisyUI-related assets for styling.
|
||||||
|
Defaults to False.
|
||||||
|
:type daisyui: Optional[bool]
|
||||||
|
|
||||||
|
:param mount_auth_app: Flag to enable or disable mounting of authentication routes.
|
||||||
|
Defaults to False.
|
||||||
|
:type mount_auth_app: Optional[bool]
|
||||||
|
|
||||||
|
:param kwargs: Arbitrary keyword arguments forwarded to the application initialization logic.
|
||||||
|
|
||||||
|
:return: A tuple containing the FastHtml application instance and the associated router.
|
||||||
|
:rtype: Any
|
||||||
|
"""
|
||||||
|
hdrs = []
|
||||||
|
|
||||||
|
if daisyui:
|
||||||
|
hdrs = [
|
||||||
|
Link(href="/myfasthtml/daisyui-5.css", rel="stylesheet", type="text/css"),
|
||||||
|
Link(href="/myfasthtml/daisyui-5-themes.css", rel="stylesheet", type="text/css"),
|
||||||
|
Script(src="/myfasthtml/tailwindcss-browser@4.js"),
|
||||||
|
]
|
||||||
|
|
||||||
|
app, rt = fasthtml.fastapp.fast_app(hdrs=tuple(hdrs), **kwargs)
|
||||||
|
|
||||||
|
# remove the global static files routes
|
||||||
|
static_route_exts_get = app.routes.pop(0)
|
||||||
|
|
||||||
|
# Serve assets
|
||||||
|
@app.get("/myfasthtml/{filename:path}.{ext:static}")
|
||||||
|
def serve_asset(filename: str, ext: str):
|
||||||
|
path = filename + "." + ext
|
||||||
|
try:
|
||||||
|
content = get_asset_content(path)
|
||||||
|
|
||||||
|
if filename.endswith('.css'):
|
||||||
|
return Response(content, media_type="text/css")
|
||||||
|
elif filename.endswith('.js'):
|
||||||
|
return Response(content, media_type="application/javascript")
|
||||||
|
else:
|
||||||
|
return Response(content)
|
||||||
|
except Exception as e:
|
||||||
|
return Response(f"Asset not found: {path}", status_code=404)
|
||||||
|
|
||||||
|
# and put it back after the myfasthtml static files routes
|
||||||
|
app.routes.append(static_route_exts_get)
|
||||||
|
|
||||||
|
if mount_auth_app:
|
||||||
|
# Setup authentication routes
|
||||||
|
setup_auth_routes(app, rt)
|
||||||
|
|
||||||
|
return app, rt
|
||||||
Reference in New Issue
Block a user