openwebrx-clone/owrx/http.py

159 lines
6.8 KiB
Python
Raw Normal View History

from owrx.controllers.status import StatusController
2021-01-20 16:01:46 +00:00
from owrx.controllers.template import IndexController, MapController, FeatureController
from owrx.controllers.assets import OwrxAssetsController, AprsSymbolsController, CompiledAssetsController
from owrx.controllers.websocket import WebSocketController
from owrx.controllers.api import ApiController
from owrx.controllers.metrics import MetricsController
from owrx.controllers.settings import SettingsController
from owrx.controllers.settings.general import GeneralSettingsController
from owrx.controllers.settings.sdr import SdrSettingsController
from owrx.controllers.settings.reporting import ReportingController
2021-02-15 14:56:17 +00:00
from owrx.controllers.settings.backgrounddecoding import BackgroundDecodingController
from owrx.controllers.settings.decoding import DecodingSettingsController
from owrx.controllers.bookmarks import BookmarksController
2020-02-23 18:23:18 +00:00
from owrx.controllers.session import SessionController
from owrx.controllers.profile import ProfileController
2021-02-08 22:29:24 +00:00
from owrx.controllers.imageupload import ImageUploadController
2019-05-03 20:59:24 +00:00
from http.server import BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
import re
2020-02-23 16:53:02 +00:00
from abc import ABC, abstractmethod
2020-02-23 20:52:13 +00:00
from http.cookies import SimpleCookie
2019-05-03 20:59:24 +00:00
2019-05-10 19:50:58 +00:00
import logging
2019-05-10 19:50:58 +00:00
logger = logging.getLogger(__name__)
2019-09-22 18:51:33 +00:00
logger.setLevel(logging.INFO)
2019-05-10 19:50:58 +00:00
2019-05-03 20:59:24 +00:00
class RequestHandler(BaseHTTPRequestHandler):
def __init__(self, request, client_address, server):
self.router = Router()
super().__init__(request, client_address, server)
2019-09-22 18:51:33 +00:00
def log_message(self, format, *args):
2019-09-23 01:15:24 +00:00
logger.debug("%s - - [%s] %s", self.address_string(), self.log_date_time_string(), format % args)
2019-09-22 18:51:33 +00:00
2019-05-03 20:59:24 +00:00
def do_GET(self):
self.router.route(self, self.get_request("GET"))
2020-02-23 19:25:36 +00:00
def do_POST(self):
self.router.route(self, self.get_request("POST"))
2021-02-14 15:51:16 +00:00
def do_DELETE(self):
self.router.route(self, self.get_request("DELETE"))
def get_request(self, method):
url = urlparse(self.path)
return Request(url, method, self.headers)
2019-05-03 20:59:24 +00:00
class Request(object):
def __init__(self, url, method, headers):
2020-02-23 16:53:02 +00:00
self.path = url.path
self.query = parse_qs(url.query)
self.matches = None
2020-02-23 19:25:36 +00:00
self.method = method
self.headers = headers
self.cookies = SimpleCookie()
if "Cookie" in headers:
self.cookies.load(headers["Cookie"])
2020-02-23 16:53:02 +00:00
def setMatches(self, matches):
self.matches = matches
2020-02-23 16:53:02 +00:00
class Route(ABC):
2020-02-23 19:25:36 +00:00
def __init__(self, controller, method="GET", options=None):
2020-02-23 16:53:02 +00:00
self.controller = controller
2020-02-23 19:25:36 +00:00
self.controllerOptions = options if options is not None else {}
self.method = method
2020-02-23 16:53:02 +00:00
@abstractmethod
def matches(self, request):
pass
class StaticRoute(Route):
2020-02-23 19:25:36 +00:00
def __init__(self, route, controller, method="GET", options=None):
2020-02-23 16:53:02 +00:00
self.route = route
2020-02-23 19:25:36 +00:00
super().__init__(controller, method, options)
2020-02-23 16:53:02 +00:00
def matches(self, request):
2020-02-23 19:25:36 +00:00
return request.path == self.route and self.method == request.method
2020-02-23 16:53:02 +00:00
class RegexRoute(Route):
2020-02-23 19:25:36 +00:00
def __init__(self, regex, controller, method="GET", options=None):
2020-02-23 16:53:02 +00:00
self.regex = re.compile(regex)
2020-02-23 19:25:36 +00:00
super().__init__(controller, method, options)
2020-02-23 16:53:02 +00:00
def matches(self, request):
matches = self.regex.match(request.path)
# this is probably not the cleanest way to do it...
request.setMatches(matches)
2020-02-23 19:25:36 +00:00
return matches is not None and self.method == request.method
2020-02-23 16:53:02 +00:00
2019-05-03 20:59:24 +00:00
class Router(object):
2020-02-23 16:53:02 +00:00
def __init__(self):
self.routes = [
StaticRoute("/", IndexController),
2020-06-01 14:03:22 +00:00
StaticRoute("/status.json", StatusController),
2020-02-23 16:53:02 +00:00
RegexRoute("/static/(.+)", OwrxAssetsController),
RegexRoute("/compiled/(.+)", CompiledAssetsController),
2020-02-23 16:53:02 +00:00
RegexRoute("/aprs-symbols/(.+)", AprsSymbolsController),
StaticRoute("/ws/", WebSocketController),
RegexRoute("(/favicon.ico)", OwrxAssetsController),
StaticRoute("/map", MapController),
StaticRoute("/features", FeatureController),
StaticRoute("/api/features", ApiController),
2021-02-01 17:43:14 +00:00
StaticRoute("/metrics", MetricsController, options={"action": "prometheusAction"}),
2021-02-01 17:26:26 +00:00
StaticRoute("/metrics.json", MetricsController),
2020-04-25 19:42:00 +00:00
StaticRoute("/settings", SettingsController),
2021-02-13 15:44:14 +00:00
StaticRoute("/settings/general", GeneralSettingsController),
2021-01-20 16:01:46 +00:00
StaticRoute(
2021-02-13 15:44:14 +00:00
"/settings/general", GeneralSettingsController, method="POST", options={"action": "processFormData"}
2021-01-20 16:01:46 +00:00
),
2021-02-13 15:44:14 +00:00
StaticRoute("/settings/sdr", SdrSettingsController),
StaticRoute("/settings/bookmarks", BookmarksController),
2021-02-14 15:21:09 +00:00
StaticRoute("/settings/bookmarks", BookmarksController, method="POST", options={"action": "new"}),
2021-02-13 23:41:03 +00:00
RegexRoute("/settings/bookmarks/(.+)", BookmarksController, method="POST", options={"action": "update"}),
2021-02-14 15:51:16 +00:00
RegexRoute("/settings/bookmarks/(.+)", BookmarksController, method="DELETE", options={"action": "delete"}),
StaticRoute("/settings/reporting", ReportingController),
StaticRoute(
"/settings/reporting", ReportingController, method="POST", options={"action": "processFormData"}
),
2021-02-15 14:56:17 +00:00
StaticRoute("/settings/backgrounddecoding", BackgroundDecodingController),
StaticRoute(
"/settings/backgrounddecoding",
BackgroundDecodingController,
method="POST",
options={"action": "processFormData"},
),
StaticRoute("/settings/decoding", DecodingSettingsController),
StaticRoute(
"/settings/decoding", DecodingSettingsController, method="POST", options={"action": "processFormData"}
),
2020-02-23 19:25:36 +00:00
StaticRoute("/login", SessionController, options={"action": "loginAction"}),
StaticRoute("/login", SessionController, method="POST", options={"action": "processLoginAction"}),
StaticRoute("/logout", SessionController, options={"action": "logoutAction"}),
StaticRoute("/pwchange", ProfileController),
StaticRoute("/pwchange", ProfileController, method="POST", options={"action": "processPwChange"}),
2021-02-08 22:29:24 +00:00
StaticRoute("/imageupload", ImageUploadController),
StaticRoute("/imageupload", ImageUploadController, method="POST", options={"action": "processImage"}),
2020-02-23 16:53:02 +00:00
]
def find_route(self, request):
for r in self.routes:
if r.matches(request):
return r
def route(self, handler, request):
2020-02-23 16:53:02 +00:00
route = self.find_route(request)
if route is not None:
controller = route.controller
controller(handler, request, route.controllerOptions).handle_request()
2019-05-03 20:59:24 +00:00
else:
handler.send_error(404, "Not Found", "The page you requested could not be found.")