From 95341a2c07ae8847ab22e62b2f59ff264bea96c1 Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Fri, 17 Nov 2023 11:07:40 -0500 Subject: [PATCH] Generalize static file setup. --- src/allmydata/web/common.py | 28 ++++++++++++++++++++++++++++ src/allmydata/web/introweb.py | 18 +++--------------- src/allmydata/web/root.py | 18 ++---------------- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/allmydata/web/common.py b/src/allmydata/web/common.py index 1a0ba433b..2a3a9ea1c 100644 --- a/src/allmydata/web/common.py +++ b/src/allmydata/web/common.py @@ -4,6 +4,8 @@ Ported to Python 3. from __future__ import annotations from six import ensure_str +from importlib.resources import files as resource_files, as_file +from contextlib import ExitStack from typing import Optional, Union, TypeVar, overload from typing_extensions import Literal @@ -29,6 +31,7 @@ from twisted.web import ( http, resource, template, + static, ) from twisted.web.iweb import ( IRequest, @@ -852,3 +855,28 @@ def get_keypair(request: IRequest) -> tuple[PublicKey, PrivateKey] | None: return None privkey, pubkey = create_signing_keypair_from_string(urlsafe_b64decode(privkey_der)) return pubkey, privkey + + +class StaticFiles: + """ + Serve static files includes as resources. + + Package resources may be on the filesystem, or they may be in a zip + or something, so we need to do a bit more work to serve them as + static files. + """ + + def __init__(self): + self._temporary_file_manager = ExitStack() + + @classmethod + def add_static_children(cls, root: IResource): + """Add static files from C{allmydata.web} to the given resource.""" + self = cls() + static_dir = resource_files("allmydata.web") / "static" + for child in static_dir.iterdir(): + child_path = child.name.encode("utf-8") + root.putChild(child_path, static.File( + self._temporary_file_manager.enter_context(as_file(child)) + )) + root.__static_files_cleanup = self diff --git a/src/allmydata/web/introweb.py b/src/allmydata/web/introweb.py index 621a15a5c..880ff66e5 100644 --- a/src/allmydata/web/introweb.py +++ b/src/allmydata/web/introweb.py @@ -1,26 +1,16 @@ """ Ported to Python 3. """ -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - -from future.utils import PY2 -if PY2: - from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401 - -import time, os -from pkg_resources import resource_filename +import time from twisted.web.template import Element, XMLFile, renderElement, renderer from twisted.python.filepath import FilePath -from twisted.web import static import allmydata from allmydata.util import idlib, jsonbytes as json from allmydata.web.common import ( render_time, MultiFormatResource, SlotsSequenceElement, + StaticFiles ) @@ -38,9 +28,7 @@ class IntroducerRoot(MultiFormatResource): self.introducer_service = introducer_node.getServiceNamed("introducer") # necessary as a root Resource self.putChild(b"", self) - static_dir = resource_filename("allmydata.web", "static") - for filen in os.listdir(static_dir): - self.putChild(filen.encode("utf-8"), static.File(os.path.join(static_dir, filen))) + StaticFiles.add_static_children(self) def _create_element(self): """ diff --git a/src/allmydata/web/root.py b/src/allmydata/web/root.py index 642912279..d8ef360c9 100644 --- a/src/allmydata/web/root.py +++ b/src/allmydata/web/root.py @@ -4,8 +4,6 @@ Ported to Python 3. import os import time from urllib.parse import quote as urlquote -from importlib.resources import files as resource_files, as_file -from contextlib import ExitStack from hyperlink import DecodedURL, URL from twisted.web import ( @@ -46,6 +44,7 @@ from allmydata.web.common import ( render_time_delta, render_time, render_time_attr, + StaticFiles, ) from allmydata.web.private import ( create_private_tree, @@ -243,22 +242,9 @@ class Root(MultiFormatResource): self.putChild(b"named", FileHandler(client)) self.putChild(b"status", status.Status(client.get_history())) self.putChild(b"statistics", status.Statistics(client.stats_provider)) - - # Package resources may be on the filesystem, or they may be in a zip - # or something, so we need to do a bit more work to serve them as - # static files. - self._temporary_file_manager = ExitStack() - static_dir = resource_files("allmydata.web") / "static" - for child in static_dir.iterdir(): - child_path = child.name.encode("utf-8") - self.putChild(child_path, static.File( - self._temporary_file_manager.enter_context(as_file(child)) - )) - self.putChild(b"report_incident", IncidentReporter()) - def __del__(self): - self._temporary_file_manager.close() + StaticFiles.add_static_children(self) @exception_to_child def getChild(self, path, request):