openwebrx-clone/owrx/http.py

197 lines
8.3 KiB
Python
Raw Normal View History

from owrx.controllers.status import StatusController
from owrx.controllers.template import IndexController, MapController
from owrx.controllers.feature import FeatureController
2021-01-20 16:01:46 +00:00
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 (
SdrDeviceListController,
SdrDeviceController,
SdrProfileController,
NewSdrDeviceController,
2021-03-03 21:33:37 +00:00
NewProfileController,
)
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
2021-02-27 00:16:03 +00:00
from owrx.controllers.settings.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
from owrx.controllers.robots import RobotsController
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
class Request(object):
def __init__(self, url, method, headers):
2021-03-03 14:24:18 +00:00
parsed_url = urlparse(url)
self.path = parsed_url.path
self.query = parse_qs(parsed_url.query)
2020-02-23 16:53:02 +00:00
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),
StaticRoute("/robots.txt", RobotsController),
2020-06-01 14:03:22 +00:00
StaticRoute("/status.json", StatusController),
2021-02-20 22:45:06 +00:00
RegexRoute("^/static/(.+)$", OwrxAssetsController),
RegexRoute("^/compiled/(.+)$", CompiledAssetsController),
RegexRoute("^/aprs-symbols/(.+)$", AprsSymbolsController),
2020-02-23 16:53:02 +00:00
StaticRoute("/ws/", WebSocketController),
2021-02-20 22:45:06 +00:00
RegexRoute("^(/favicon.ico)$", OwrxAssetsController),
2020-02-23 16:53:02 +00:00
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
),
StaticRoute("/settings/sdr", SdrDeviceListController),
StaticRoute("/settings/newsdr", NewSdrDeviceController),
StaticRoute(
"/settings/newsdr", NewSdrDeviceController, method="POST", options={"action": "processFormData"}
),
2021-02-20 22:45:06 +00:00
RegexRoute("^/settings/sdr/([^/]+)$", SdrDeviceController),
2021-02-23 17:32:23 +00:00
RegexRoute(
"^/settings/sdr/([^/]+)$", SdrDeviceController, method="POST", options={"action": "processFormData"}
),
2021-03-03 22:07:41 +00:00
RegexRoute("^/settings/deletesdr/([^/]+)$", SdrDeviceController, options={"action": "deleteDevice"}),
2021-03-03 21:33:37 +00:00
RegexRoute("^/settings/sdr/([^/]+)/newprofile$", NewProfileController),
RegexRoute(
"^/settings/sdr/([^/]+)/newprofile$",
NewProfileController,
method="POST",
options={"action": "processFormData"},
),
2021-03-03 20:55:49 +00:00
RegexRoute("^/settings/sdr/([^/]+)/profile/([^/]+)$", SdrProfileController),
2021-02-23 17:32:23 +00:00
RegexRoute(
2021-03-03 20:55:49 +00:00
"^/settings/sdr/([^/]+)/profile/([^/]+)$",
2021-02-23 17:32:23 +00:00
SdrProfileController,
method="POST",
options={"action": "processFormData"},
),
2021-03-03 22:07:41 +00:00
RegexRoute(
"^/settings/sdr/([^/]+)/deleteprofile/([^/]+)$",
SdrProfileController,
options={"action": "deleteProfile"},
),
StaticRoute("/settings/bookmarks", BookmarksController),
2021-02-14 15:21:09 +00:00
StaticRoute("/settings/bookmarks", BookmarksController, method="POST", options={"action": "new"}),
2021-02-20 22:45:06 +00:00
RegexRoute("^/settings/bookmarks/(.+)$", BookmarksController, method="POST", options={"action": "update"}),
2021-02-23 17:32:23 +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.")
class RequestHandler(BaseHTTPRequestHandler):
timeout = 30
router = Router()
def log_message(self, format, *args):
logger.debug("%s - - [%s] %s", self.address_string(), self.log_date_time_string(), format % args)
def do_GET(self):
self.router.route(self, self._build_request("GET"))
def do_POST(self):
self.router.route(self, self._build_request("POST"))
def do_DELETE(self):
self.router.route(self, self._build_request("DELETE"))
def _build_request(self, method):
return Request(self.path, method, self.headers)