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,
|
flash,
|
||||||
abort,
|
abort,
|
||||||
jsonify,
|
jsonify,
|
||||||
session
|
session,
|
||||||
)
|
)
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from flask_login import (
|
from flask_login import (
|
||||||
@@ -47,7 +47,7 @@ PORT = 5121
|
|||||||
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////app/instance/db.sqlite"
|
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////app/instance/db.sqlite"
|
||||||
app.config["UPLOAD_FOLDER"] = "sites"
|
app.config["UPLOAD_FOLDER"] = "sites"
|
||||||
app.config["SERVER_NAME"] = "tinysite.cloud"
|
app.config["SERVER_NAME"] = "tinysite.cloud"
|
||||||
# app.config["SESSION_COOKIE_DOMAIN"] = ".tinysite.cloud"
|
app.config["SESSION_COOKIE_DOMAIN"] = ".tinysite.cloud"
|
||||||
db = SQLAlchemy(app)
|
db = SQLAlchemy(app)
|
||||||
|
|
||||||
|
|
||||||
@@ -72,11 +72,26 @@ RESERVED_SUBDOMAINS = {
|
|||||||
|
|
||||||
# TODO: add specific page redirects here as they're added
|
# TODO: add specific page redirects here as they're added
|
||||||
def isDefaultRoute(hostname: str):
|
def isDefaultRoute(hostname: str):
|
||||||
if hostname.count(".") < 2:
|
# exactly the main domain
|
||||||
|
if hostname == app.config["SERVER_NAME"]:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
subdomain = hostname.split(".")[0]
|
# a reserved subdomain
|
||||||
return not subdomain or subdomain in RESERVED_SUBDOMAINS
|
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
|
# Models
|
||||||
@@ -101,16 +116,29 @@ class Site(db.Model):
|
|||||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
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)
|
@app.errorhandler(404)
|
||||||
def page_not_found(_):
|
def page_not_found(_):
|
||||||
return render_template("404.html", domain=request.host), 404
|
return render_template("404.html", domain=request.host), 404
|
||||||
|
|
||||||
@app.context_processor
|
|
||||||
def inject_global_variable():
|
|
||||||
return {
|
|
||||||
"SERVERNAME": app.config["SERVER_NAME"],
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Auth setup
|
# Auth setup
|
||||||
login_manager = LoginManager()
|
login_manager = LoginManager()
|
||||||
@@ -327,11 +355,11 @@ def delete_file(site_id, filename):
|
|||||||
return redirect(url_for("dashboard"))
|
return redirect(url_for("dashboard"))
|
||||||
|
|
||||||
|
|
||||||
# use subdomains
|
|
||||||
@app.route("/", subdomain="<subdomain>", defaults={"filename": "index.html"})
|
@app.route("/", subdomain="<subdomain>", defaults={"filename": "index.html"})
|
||||||
@app.route("/<path:filename>")
|
@app.route("/<path:filename>", subdomain="<subdomain>")
|
||||||
def serve_site_content(filename):
|
def serve_site_content(subdomain, filename):
|
||||||
subdomain = request.host.split(".")[0]
|
if isDefaultRoute(request.host):
|
||||||
|
abort(404) # Reserve default routes for main app
|
||||||
|
|
||||||
site = Site.query.filter_by(subdomain=subdomain).first_or_404()
|
site = Site.query.filter_by(subdomain=subdomain).first_or_404()
|
||||||
site.last_accessed = datetime.utcnow()
|
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)
|
app.config["UPLOAD_FOLDER"], str(site.user_id), str(site.id)
|
||||||
)
|
)
|
||||||
|
|
||||||
if isDefaultRoute(request.host):
|
# Security checks
|
||||||
return send_from_directory("index.html")
|
|
||||||
|
|
||||||
# Security check
|
|
||||||
if ".." in filename or filename.startswith("/") or not os.path.exists(site_dir):
|
if ".." in filename or filename.startswith("/") or not os.path.exists(site_dir):
|
||||||
return render_template("404.html"), 404
|
abort(404)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return send_from_directory(site_dir, filename)
|
return send_from_directory(site_dir, filename)
|
||||||
@@ -355,7 +380,6 @@ def serve_site_content(filename):
|
|||||||
try:
|
try:
|
||||||
return send_from_directory(site_dir, f"{filename}.html")
|
return send_from_directory(site_dir, f"{filename}.html")
|
||||||
except NotFound:
|
except NotFound:
|
||||||
redirect(app.config["SERVER_NAME"])
|
|
||||||
return send_from_directory(site_dir, "index.html")
|
return send_from_directory(site_dir, "index.html")
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
@@ -374,10 +398,9 @@ def inject_utilities():
|
|||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def home():
|
def home():
|
||||||
if isDefaultRoute(request.host):
|
if not isDefaultRoute(request.host):
|
||||||
|
abort(404)
|
||||||
return render_template("home.html")
|
return render_template("home.html")
|
||||||
else:
|
|
||||||
return serve_site_content("index.html")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
+6
-7
@@ -13,14 +13,13 @@
|
|||||||
<meta property="og:description"
|
<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!">
|
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: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:card" content="{{ url_for('static', filename='hosting.png') }}">
|
||||||
<meta name="twitter:title" content="ION Static Site Hosting">
|
<meta name="twitter:title" content="ION Static Site Hosting">
|
||||||
<meta name="twitter:description"
|
<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!">
|
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') }}">
|
<meta name="twitter:image" content="{{ url_for('static', filename='hosting.png') }}">
|
||||||
|
|
||||||
|
|
||||||
<title>ION Static Site Hosting - {% block title %}{% endblock %}</title>
|
<title>ION Static Site Hosting - {% block title %}{% endblock %}</title>
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}" id="theme-style">
|
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}" id="theme-style">
|
||||||
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||||
@@ -53,13 +52,13 @@
|
|||||||
<body>
|
<body>
|
||||||
<nav class="navbar">
|
<nav class="navbar">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a href="https://{{ SERVERNAME }}">Home</a>
|
<a href="{{ url_for('home', _external=True) }}">Home</a>
|
||||||
{% if current_user.is_authenticated %}
|
{% if current_user.is_authenticated %}
|
||||||
<a href="https://{{ SERVERNAME }}/dashboard">Dashboard</a>
|
<a href="{{ url_for('dashboard', _external=True) }}">Dashboard</a>
|
||||||
<a href="https://{{ SERVERNAME }}/logout">Logout</a>
|
<a href="{{ url_for('logout', _external=True) }}">Logout</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ url_for('login') }}">Login</a>
|
<a href="{{ url_for('login', _external=True) }}">Login</a>
|
||||||
<a href="{{ url_for('register') }}">Register</a>
|
<a href="{{ url_for('register', _external=True) }}">Register</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button id="theme-toggle" class="btn">Toggle Dark Mode</button>
|
<button id="theme-toggle" class="btn">Toggle Dark Mode</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user