mirror of
https://github.com/ION606/static-site-hosting.git
synced 2026-05-14 22:16:54 +00:00
added better url fixes
This commit is contained in:
@@ -8,7 +8,7 @@ from flask import (
|
||||
flash,
|
||||
abort,
|
||||
jsonify,
|
||||
session
|
||||
session,
|
||||
)
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_login import (
|
||||
@@ -47,7 +47,7 @@ PORT = 5121
|
||||
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////app/instance/db.sqlite"
|
||||
app.config["UPLOAD_FOLDER"] = "sites"
|
||||
app.config["SERVER_NAME"] = "tinysite.cloud"
|
||||
# app.config["SESSION_COOKIE_DOMAIN"] = ".tinysite.cloud"
|
||||
app.config["SESSION_COOKIE_DOMAIN"] = ".tinysite.cloud"
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
|
||||
@@ -72,11 +72,26 @@ RESERVED_SUBDOMAINS = {
|
||||
|
||||
# TODO: add specific page redirects here as they're added
|
||||
def isDefaultRoute(hostname: str):
|
||||
if hostname.count(".") < 2:
|
||||
# exactly the main domain
|
||||
if hostname == app.config["SERVER_NAME"]:
|
||||
return True
|
||||
|
||||
subdomain = hostname.split(".")[0]
|
||||
return not subdomain or subdomain in RESERVED_SUBDOMAINS
|
||||
# a reserved subdomain
|
||||
parts = hostname.split(".")
|
||||
server_parts = app.config["SERVER_NAME"].split(".")
|
||||
|
||||
# the host ends with the server domain
|
||||
if parts[-len(server_parts) :] != server_parts:
|
||||
return False
|
||||
|
||||
# subdomain portion
|
||||
subdomain = ".".join(parts[: -len(server_parts)])
|
||||
|
||||
# any part of the subdomain is reserved
|
||||
return (
|
||||
any(part in RESERVED_SUBDOMAINS for part in subdomain.split("."))
|
||||
or subdomain in RESERVED_SUBDOMAINS
|
||||
)
|
||||
|
||||
|
||||
# Models
|
||||
@@ -101,16 +116,29 @@ class Site(db.Model):
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
|
||||
@app.context_processor
|
||||
def inject_subdomain():
|
||||
host = request.host
|
||||
server_parts = app.config["SERVER_NAME"].split(".")
|
||||
host_parts = host.split(".")
|
||||
|
||||
subdomain = None
|
||||
if host_parts[-len(server_parts) :] == server_parts:
|
||||
subdomain_parts = host_parts[: -len(server_parts)]
|
||||
if subdomain_parts:
|
||||
subdomain = ".".join(subdomain_parts)
|
||||
|
||||
return {
|
||||
"SUBDOMAIN": subdomain,
|
||||
"FULL_DOMAIN": host,
|
||||
"SERVERNAME": app.config["SERVER_NAME"],
|
||||
}
|
||||
|
||||
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(_):
|
||||
return render_template("404.html", domain=request.host), 404
|
||||
|
||||
@app.context_processor
|
||||
def inject_global_variable():
|
||||
return {
|
||||
"SERVERNAME": app.config["SERVER_NAME"],
|
||||
}
|
||||
|
||||
|
||||
# Auth setup
|
||||
login_manager = LoginManager()
|
||||
@@ -327,11 +355,11 @@ def delete_file(site_id, filename):
|
||||
return redirect(url_for("dashboard"))
|
||||
|
||||
|
||||
# use subdomains
|
||||
@app.route("/", subdomain="<subdomain>", defaults={"filename": "index.html"})
|
||||
@app.route("/<path:filename>")
|
||||
def serve_site_content(filename):
|
||||
subdomain = request.host.split(".")[0]
|
||||
@app.route("/<path:filename>", subdomain="<subdomain>")
|
||||
def serve_site_content(subdomain, filename):
|
||||
if isDefaultRoute(request.host):
|
||||
abort(404) # Reserve default routes for main app
|
||||
|
||||
site = Site.query.filter_by(subdomain=subdomain).first_or_404()
|
||||
site.last_accessed = datetime.utcnow()
|
||||
@@ -341,12 +369,9 @@ def serve_site_content(filename):
|
||||
app.config["UPLOAD_FOLDER"], str(site.user_id), str(site.id)
|
||||
)
|
||||
|
||||
if isDefaultRoute(request.host):
|
||||
return send_from_directory("index.html")
|
||||
|
||||
# Security check
|
||||
# Security checks
|
||||
if ".." in filename or filename.startswith("/") or not os.path.exists(site_dir):
|
||||
return render_template("404.html"), 404
|
||||
abort(404)
|
||||
|
||||
try:
|
||||
return send_from_directory(site_dir, filename)
|
||||
@@ -355,7 +380,6 @@ def serve_site_content(filename):
|
||||
try:
|
||||
return send_from_directory(site_dir, f"{filename}.html")
|
||||
except NotFound:
|
||||
redirect(app.config["SERVER_NAME"])
|
||||
return send_from_directory(site_dir, "index.html")
|
||||
abort(404)
|
||||
|
||||
@@ -374,10 +398,9 @@ def inject_utilities():
|
||||
|
||||
@app.route("/")
|
||||
def home():
|
||||
if isDefaultRoute(request.host):
|
||||
if not isDefaultRoute(request.host):
|
||||
abort(404)
|
||||
return render_template("home.html")
|
||||
else:
|
||||
return serve_site_content("index.html")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+6
-7
@@ -13,14 +13,13 @@
|
||||
<meta property="og:description"
|
||||
content="Host and share your static sites effortlessly with ION Static Site Hosting. Enjoy instant deployment, a sleek dark mode interface, and secure, private data handling!">
|
||||
<meta property="og:image" content="{{ url_for('static', filename='hosting.png') }}">
|
||||
<meta property="og:url" content="https://{{session['servername']}}/">
|
||||
<meta property="og:url" content="https://{{ SERVERNAME }}/">
|
||||
<meta name="twitter:card" content="{{ url_for('static', filename='hosting.png') }}">
|
||||
<meta name="twitter:title" content="ION Static Site Hosting">
|
||||
<meta name="twitter:description"
|
||||
content="Host and share your static sites effortlessly with ION Static Site Hosting. Enjoy instant deployment, a sleek dark mode interface, and secure, private data handling!">
|
||||
<meta name="twitter:image" content="{{ url_for('static', filename='hosting.png') }}">
|
||||
|
||||
|
||||
<title>ION Static Site Hosting - {% block title %}{% endblock %}</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}" id="theme-style">
|
||||
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||
@@ -53,13 +52,13 @@
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<div class="container">
|
||||
<a href="https://{{ SERVERNAME }}">Home</a>
|
||||
<a href="{{ url_for('home', _external=True) }}">Home</a>
|
||||
{% if current_user.is_authenticated %}
|
||||
<a href="https://{{ SERVERNAME }}/dashboard">Dashboard</a>
|
||||
<a href="https://{{ SERVERNAME }}/logout">Logout</a>
|
||||
<a href="{{ url_for('dashboard', _external=True) }}">Dashboard</a>
|
||||
<a href="{{ url_for('logout', _external=True) }}">Logout</a>
|
||||
{% else %}
|
||||
<a href="{{ url_for('login') }}">Login</a>
|
||||
<a href="{{ url_for('register') }}">Register</a>
|
||||
<a href="{{ url_for('login', _external=True) }}">Login</a>
|
||||
<a href="{{ url_for('register', _external=True) }}">Register</a>
|
||||
{% endif %}
|
||||
<button id="theme-toggle" class="btn">Toggle Dark Mode</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user