# HG changeset patch # User Goffi # Date 1587931273 -7200 # Node ID aaf28d45ae679f903da4cdf060e2dba36be914ae # Parent 079e8eb6e327017e3506daeb92b1ea3bec07c95b pages: browser code, first draft: - code for browser can now be specified if a page subdirectory named `_browser` exists - the default engine used is `Brython` (not yet implemented, so it will do nothing for now) - build_path now uses C.SITE_NAME_DEFAULT for default site instead of empty string, to avoid collision with other sites - ProtectedFile transtype path (first positional argument) to str, so a pathlib.Path can be used diff -r 079e8eb6e327 -r aaf28d45ae67 libervia/server/constants.py --- a/libervia/server/constants.py Sat Apr 25 16:08:55 2020 +0200 +++ b/libervia/server/constants.py Sun Apr 26 22:01:13 2020 +0200 @@ -35,7 +35,9 @@ PAGES_DIR = "pages" TASKS_DIR = "tasks" LIBERVIA_CACHE = "libervia" + SITE_NAME_DEFAULT = "default" BUILD_DIR = "__b" + BUILD_DIR_DYN = "dyn" TPL_RESOURCE = '_t' @@ -57,6 +59,7 @@ ## Libervia pages ## PAGES_META_FILE = "page_meta.py" + PAGES_BROWSER_DIR = "_browser" PAGES_ACCESS_NONE = ( "none" ) #  no access to this page (using its path will return a 404 error) diff -r 079e8eb6e327 -r aaf28d45ae67 libervia/server/pages.py --- a/libervia/server/pages.py Sat Apr 25 16:08:55 2020 +0200 +++ b/libervia/server/pages.py Sun Apr 26 22:01:13 2020 +0200 @@ -16,6 +16,16 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . + +import uuid +import os.path +import urllib.request, urllib.parse, urllib.error +import time +import hashlib +import copy +from functools import reduce +from pathlib import Path + from twisted.web import server from twisted.web import resource as web_resource from twisted.web import util as web_util @@ -34,14 +44,6 @@ from libervia.server.utils import quote, SubPage from libervia.server.classes import WebsocketMeta -import uuid -import os.path -import urllib.request, urllib.parse, urllib.error -import time -import hashlib -import copy -from functools import reduce - log = getLogger(__name__) @@ -173,6 +175,7 @@ self.root_dir = root_dir self.url = url self.name = name + self.dyn_data = {} if name is not None: if (name in self.named_pages and not (replace_on_conflict and self.named_pages[name].url == url)): @@ -331,7 +334,8 @@ if os.path.isfile(meta_path): new_path = _path + [d] try: - page_data, resource = cls.createPage(host, meta_path, vhost_root, new_path) + page_data, resource = cls.createPage( + host, meta_path, vhost_root, new_path) except exceptions.ConflictError as e: if _extra_pages: # extra pages are discarded if there is already an existing page @@ -369,6 +373,18 @@ LiberviaPage.importPages( host, vhost_root, _parent=resource, _path=new_path, _extra_pages=_extra_pages) + # now we check if there is some code for browser + browser_path = Path(dir_path) / C.PAGES_BROWSER_DIR + if browser_path.is_dir(): + # for now we only handle Brython + dyn_data = { + "path": browser_path, + "url_hash": hashlib.sha256( + '/'.join(new_path).encode()).hexdigest(), + } + vhost_root.browser_modules.setdefault( + "brython", []).append(dyn_data) + resource.dyn_data['brython'] = dyn_data @classmethod def onFileChange(cls, host, file_path, flags, site_root, site_path): @@ -1257,6 +1273,16 @@ template_data['locale'] = session_data.locale if self.vhost_root.site_name: template_data['site'] = self.vhost_root.site_name + if self.dyn_data: + for data in self.dyn_data.values(): + template_data_dyn = data.get('template', {}) + try: + scripts = template_data_dyn['scripts'] + except KeyError: + pass + else: + template_data.setdefault('scripts', []).extend(scripts) + template_data.update(template_data_dyn) return self.host.renderer.render( self.template, diff -r 079e8eb6e327 -r aaf28d45ae67 libervia/server/server.py --- a/libervia/server/server.py Sat Apr 25 16:08:55 2020 +0200 +++ b/libervia/server/server.py Sun Apr 26 22:01:13 2020 +0200 @@ -125,13 +125,13 @@ class ProtectedFile(static.File): """A static.File class which doesn't show directory listing""" - def __init__(self, *args, **kwargs): + def __init__(self, path, *args, **kwargs): if "defaultType" not in kwargs and len(args) < 2: # defaultType is second positional argument, and Twisted uses it # in File.createSimilarFile, so we set kwargs only if it is missing # in kwargs and it is not in a positional argument kwargs["defaultType"] = "application/octet-stream" - super(ProtectedFile, self).__init__(*args, **kwargs) + super(ProtectedFile, self).__init__(str(path), *args, **kwargs) def directoryListing(self): return web_resource.NoResource() @@ -159,10 +159,19 @@ self.site_name = site_name self.site_path = site_path self.named_pages = {} + self.browser_modules = {} self.uri_callbacks = {} self.pages_redirects = {} self.cached_urls = {} self.main_menu = None + build_path = host.getBuildPath(site_name) + build_path.mkdir(parents=True, exist_ok=True) + self.putChild( + C.BUILD_DIR.encode(), + ProtectedFile( + build_path, + defaultType="application/octet-stream"), + ) def __str__(self): return ("Root resource for {host_name} using {site_name} at {site_path} and " @@ -755,8 +764,8 @@ # self.sat_root is official Libervia site root_path = os.path.join(default_site_path, C.TEMPLATE_STATIC_DIR) self.sat_root = default_root = LiberviaRootResource( - host=self, host_name='', site_name='', site_path=default_site_path, - path=root_path) + host=self, host_name='', site_name='', + site_path=default_site_path, path=root_path) if self.options['dev_mode']: self.files_watcher.watchDir( default_site_path, auto_add=True, recursive=True, @@ -772,6 +781,9 @@ existing_vhosts = {b'': default_root} for host_name, site_name in self.options["vhosts_dict"].items(): + if site_name == C.SITE_NAME_DEFAULT: + raise ValueError( + f"{C.DEFAULT_SITE_NAME} is reserved and can't be used in vhosts_dict") encoded_site_name = site_name.encode('utf-8') try: site_path = self.renderer.sites_paths[site_name] @@ -805,12 +817,6 @@ site_path, auto_add=True, recursive=True, callback=LiberviaPage.onFileChange, site_root=res, site_path=site_path) - res.putChild( - C.BUILD_DIR.encode('utf-8'), - ProtectedFile( - self.getBuildPath(site_name), - defaultType="application/octet-stream"), - ) LiberviaPage.importPages(self, res) # FIXME: default pages are accessible if not overriden by external website @@ -1277,15 +1283,15 @@ """Generate build path for a given site name @param site_name(unicode): name of the site - @return (unicode): path to the build directory + @return (Path): path to the build directory """ build_path_elts = [ config.getConfig(self.main_conf, "", "local_dir"), C.CACHE_DIR, C.LIBERVIA_CACHE, - regex.pathEscape(site_name)] - build_path = "/".join(build_path_elts) - return os.path.abspath(os.path.expanduser(build_path)) + regex.pathEscape(site_name or C.SITE_NAME_DEFAULT)] + build_path = Path("/".join(build_path_elts)) + return build_path.expanduser().resolve() def getExtBaseURLData(self, request): """Retrieve external base URL Data