fix: handle all errors

This commit is contained in:
2026-04-27 15:18:42 +02:00
committed by Kleπek
parent 95514f16cb
commit a2e0f9afb9
2 changed files with 77 additions and 64 deletions
+4 -2
View File
@@ -122,7 +122,9 @@ class CertManager:
) )
self.logger.info("Created self-signed certificate for %s", host) self.logger.info("Created self-signed certificate for %s", host)
except CertManagerError: except CertManagerError:
self.logger.exception("Could not create certbot certificate for %s\n%s") self.logger.exception(
"Could not create self-signed certificate for %s", host
)
return False return False
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
self.logger.exception( self.logger.exception(
@@ -172,7 +174,7 @@ class CertManager:
) )
self.logger.info("Created certbot certificate for %s", host) self.logger.info("Created certbot certificate for %s", host)
except CertManagerError: except CertManagerError:
self.logger.exception("Could not create certbot certificate for %s\n%s") self.logger.exception("Could not create certbot certificate for %s", host)
return False return False
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
self.logger.exception( self.logger.exception(
+73 -62
View File
@@ -1,4 +1,5 @@
import abc import abc
import contextlib
import http import http
import http.cookiejar import http.cookiejar
import http.server import http.server
@@ -223,6 +224,14 @@ class BaseHandler(abc.ABC, http.server.BaseHTTPRequestHandler):
def server_signature(self) -> str: def server_signature(self) -> str:
return self.server_version + "\n\n" + STAPLER_ASCII + "\n" return self.server_version + "\n\n" + STAPLER_ASCII + "\n"
@contextlib.contextmanager
def handle_errors(self) -> typing.Iterator[None]:
try:
yield
except Exception as e:
self.send_error(http.HTTPStatus.INTERNAL_SERVER_ERROR, str(e))
self.logger.exception("Internal Server Error")
class RequestHandler(http.server.SimpleHTTPRequestHandler, BaseHandler): class RequestHandler(http.server.SimpleHTTPRequestHandler, BaseHandler):
protocol_version = "HTTP/1.1" protocol_version = "HTTP/1.1"
@@ -335,42 +344,45 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler, BaseHandler):
@typing.override @typing.override
def do_HEAD(self) -> None: def do_HEAD(self) -> None:
self._pre_log_request() with self.handle_errors():
if not self._proxy_or_redirect(): self._pre_log_request()
super().do_HEAD() if not self._proxy_or_redirect():
super().do_HEAD()
@typing.override @typing.override
def do_GET(self) -> None: def do_GET(self) -> None:
self._pre_log_request() with self.handle_errors():
if self._proxy_or_redirect(): self._pre_log_request()
return None if self._proxy_or_redirect():
if self.path == "/" and self.host == self.default_host: return None
return self.send_basic_body(self.server_signature()) if self.path == "/" and self.host == self.default_host:
return super().do_GET() return self.send_basic_body(self.server_signature())
return super().do_GET()
def do_PUT(self) -> None: def do_PUT(self) -> None:
self._pre_log_request() with self.handle_errors():
if self._proxy_or_redirect(): self._pre_log_request()
return if self._proxy_or_redirect():
if (path := self.__check_put_request()) is None:
return
if self.has_target_redirect:
if not self._update_redirect(path):
return return
elif self.has_target_proxy: if (path := self.__check_put_request()) is None:
if not self._update_proxy(path):
return return
elif not self._update_extract(path): if self.has_target_redirect:
return if not self._update_redirect(path):
if self.has_request_host: return
self.registry.set_host(path, self.target_host) elif self.has_target_proxy:
if self.has_request_host_only: if not self._update_proxy(path):
self.registry.set_host_only(path, self.target_host) return
self.send_status( elif not self._update_extract(path):
http.HTTPStatus.CREATED, return
"Resource updated", if self.has_request_host:
str(self.registry.get_from_path(path)), self.registry.set_host(path, self.target_host)
) if self.has_request_host_only:
self.registry.set_host_only(path, self.target_host)
self.send_status(
http.HTTPStatus.CREATED,
"Resource updated",
str(self.registry.get_from_path(path)),
)
def do_POST(self) -> None: def do_POST(self) -> None:
self.do_PUT() # be gentle on them self.do_PUT() # be gentle on them
@@ -379,32 +391,36 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler, BaseHandler):
self.do_PUT() # be gentle on them self.do_PUT() # be gentle on them
def do_DELETE(self) -> None: def do_DELETE(self) -> None:
self._pre_log_request() with self.handle_errors():
if self._proxy_or_redirect(): self._pre_log_request()
if self._proxy_or_redirect():
return
if (path := self.__check_update_request()) is None:
return
if self._update_remove(path):
self.send_status(
http.HTTPStatus.OK,
f"Resource /{path}/ removed",
)
return return
if (path := self.__check_update_request()) is None:
return
if self._update_remove(path):
self.send_status(
http.HTTPStatus.OK,
f"Resource /{path}/ removed",
)
return
def do_CONNECT(self) -> None: def do_CONNECT(self) -> None:
self._pre_log_request() with self.handle_errors():
if not self._proxy_or_redirect(): self._pre_log_request()
self.send_error(http.HTTPStatus.METHOD_NOT_ALLOWED) if not self._proxy_or_redirect():
self.send_error(http.HTTPStatus.METHOD_NOT_ALLOWED)
def do_OPTIONS(self) -> None: def do_OPTIONS(self) -> None:
self._pre_log_request() with self.handle_errors():
if not self._proxy_or_redirect(): self._pre_log_request()
self.send_error(http.HTTPStatus.METHOD_NOT_ALLOWED) if not self._proxy_or_redirect():
self.send_error(http.HTTPStatus.METHOD_NOT_ALLOWED)
def do_TRACE(self) -> None: def do_TRACE(self) -> None:
self._pre_log_request() with self.handle_errors():
if not self._proxy_or_redirect(): self._pre_log_request()
self.send_error(http.HTTPStatus.METHOD_NOT_ALLOWED) if not self._proxy_or_redirect():
self.send_error(http.HTTPStatus.METHOD_NOT_ALLOWED)
def _update_extract(self, path: str) -> bool: def _update_extract(self, path: str) -> bool:
if self.in_size == 0: if self.in_size == 0:
@@ -422,9 +438,6 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler, BaseHandler):
except tarfile.TarError: except tarfile.TarError:
self.send_error(http.HTTPStatus.BAD_REQUEST, "Invalid tar archive") self.send_error(http.HTTPStatus.BAD_REQUEST, "Invalid tar archive")
return False return False
except Exception as e:
self.send_error(http.HTTPStatus.INTERNAL_SERVER_ERROR, str(e))
return False
self.registry.add(path) self.registry.add(path)
self.token_manager.set_token(path, self.token) self.token_manager.set_token(path, self.token)
if self.has_target_spa: if self.has_target_spa:
@@ -457,11 +470,7 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler, BaseHandler):
if not self.data_dir.exists(path): if not self.data_dir.exists(path):
self.send_error(http.HTTPStatus.NOT_FOUND, "Not found") self.send_error(http.HTTPStatus.NOT_FOUND, "Not found")
return False return False
try: self.data_dir.remove(path)
self.data_dir.remove(path)
except Exception as e:
self.send_error(http.HTTPStatus.INTERNAL_SERVER_ERROR, str(e))
return False
self.registry.remove(path) self.registry.remove(path)
return True return True
@@ -578,11 +587,13 @@ class UpgradeHandler(RequestHandler):
server_version = "StaplerUpgradeServer/" + PKG_VERSION server_version = "StaplerUpgradeServer/" + PKG_VERSION
def do_HEAD(self) -> None: def do_HEAD(self) -> None:
self._pre_log_request() with self.handle_errors():
self.send_redirect(f"https://{self.host}{self.path}") self._pre_log_request()
self.send_redirect(f"https://{self.host}{self.path}")
def do_GET(self) -> None: def do_GET(self) -> None:
if self.path.startswith(self.CERTBOT_CHALLENGE_PATH): with self.handle_errors():
super().do_GET() if self.path.startswith(self.CERTBOT_CHALLENGE_PATH):
else: super().do_GET()
self.do_HEAD() else:
self.do_HEAD()