diff options
author | 2021-10-10 22:19:26 +0300 | |
---|---|---|
committer | 2021-10-10 23:06:46 +0300 | |
commit | a7e9bdd9dbf086094dd138feb9464b7e7fe8b08b (patch) | |
tree | dddc532795211cae019b686d25edca7285828cc2 | |
parent | Merge pull request #609 from python-discord/static-previews (diff) |
Adds Redirects To Static Builds
Dynamically adds static HTML redirects for static builds.
Signed-off-by: Hassan Abouelela <[email protected]>
-rw-r--r-- | pydis_site/apps/redirect/redirects.yaml | 2 | ||||
-rw-r--r-- | pydis_site/apps/redirect/urls.py | 114 | ||||
-rw-r--r-- | pydis_site/urls.py | 16 |
3 files changed, 112 insertions, 20 deletions
diff --git a/pydis_site/apps/redirect/redirects.yaml b/pydis_site/apps/redirect/redirects.yaml index def4154b..9bcf3afd 100644 --- a/pydis_site/apps/redirect/redirects.yaml +++ b/pydis_site/apps/redirect/redirects.yaml @@ -182,7 +182,7 @@ events_game_jams_twenty_twenty_rules_redirect: redirect_arguments: ["game-jams/2020/rules"] events_game_jams_twenty_twenty_technical_requirements_redirect: - original_path: pages/events/game-jam-2020/technical-requirements + original_path: pages/events/game-jam-2020/technical-requirements/ redirect_route: "events:page" redirect_arguments: ["game-jams/2020/technical-requirements"] diff --git a/pydis_site/apps/redirect/urls.py b/pydis_site/apps/redirect/urls.py index 6187af17..f7ddf45b 100644 --- a/pydis_site/apps/redirect/urls.py +++ b/pydis_site/apps/redirect/urls.py @@ -1,19 +1,105 @@ +import dataclasses +import re + import yaml -from django.conf import settings -from django.urls import path +from django import conf +from django.urls import URLPattern, path +from django_distill import distill_path +from pydis_site import settings +from pydis_site.apps.content import urls as pages_urls from pydis_site.apps.redirect.views import CustomRedirectView +from pydis_site.apps.resources import urls as resources_urls app_name = "redirect" -urlpatterns = [ - path( - data["original_path"], - CustomRedirectView.as_view( - pattern_name=data["redirect_route"], - static_args=tuple(data.get("redirect_arguments", ())), - prefix_redirect=data.get("prefix_redirect", False) - ), - name=name - ) - for name, data in yaml.safe_load(settings.REDIRECTIONS_PATH.read_text()).items() -] + + +__PARAMETER_REGEX = re.compile(r"<\w+:\w+>") +REDIRECT_TEMPLATE = "<meta http-equiv=\"refresh\" content=\"0; URL={url}\"/>" + + [email protected](frozen=True) +class Redirect: + """Metadata about a redirect route.""" + + original_path: str + redirect_route: str + redirect_arguments: tuple[str] = tuple() + + prefix_redirect: bool = False + + +def map_redirect(name: str, data: Redirect) -> list[URLPattern]: + """Return a pattern using the Redirects app, or a static HTML redirect for static builds.""" + if not settings.env("STATIC_BUILD"): + # Normal dynamic redirect + return [path( + data.original_path, + CustomRedirectView.as_view( + pattern_name=data.redirect_route, + static_args=tuple(data.redirect_arguments), + prefix_redirect=data.prefix_redirect + ), + name=name + )] + + # Create static HTML redirects for static builds + new_app_name = data.redirect_route.split(":")[0] + + if __PARAMETER_REGEX.search(data.original_path): + # Redirects for paths which accept parameters + # We generate an HTML redirect file for all possible entries + paths = [] + + class RedirectFunc: + def __init__(self, new_url: str, _name: str): + self.result = REDIRECT_TEMPLATE.format(url=new_url) + self.__qualname__ = _name + + def __call__(self, *args, **kwargs): + return self.result + + if new_app_name == resources_urls.app_name: + items = resources_urls.get_all_resources() + elif new_app_name == pages_urls.app_name: + items = pages_urls.get_all_pages() + else: + raise ValueError(f"Unknown app in redirect: {new_app_name}") + + for item in items: + entry = list(item.values())[0] + + # Replace dynamic redirect with concrete path + concrete_path = __PARAMETER_REGEX.sub(entry, data.original_path) + new_redirect = f"/{new_app_name}/{entry}" + pattern_name = f"{name}_{entry}" + + paths.append(distill_path( + concrete_path, + RedirectFunc(new_redirect, pattern_name), + name=pattern_name + )) + + return paths + + else: + redirect_path_name = "pages" if new_app_name == "content" else new_app_name + if len(data.redirect_arguments) > 0: + redirect_arg = data.redirect_arguments[0] + else: + redirect_arg = "resources/" + new_redirect = f"/{redirect_path_name}/{redirect_arg}" + + if new_redirect == "/resources/resources/": + new_redirect = "/resources/" + + return [distill_path( + data.original_path, + lambda *args: REDIRECT_TEMPLATE.format(url=new_redirect), + name=name, + )] + + +urlpatterns = [] +for _name, _data in yaml.safe_load(conf.settings.REDIRECTIONS_PATH.read_text()).items(): + urlpatterns.extend(map_redirect(_name, Redirect(**_data))) diff --git a/pydis_site/urls.py b/pydis_site/urls.py index 51ef4214..6cd31f26 100644 --- a/pydis_site/urls.py +++ b/pydis_site/urls.py @@ -11,19 +11,25 @@ NON_STATIC_PATTERNS = [ # Internal API ingress (cluster local) path('pydis-api/', include('pydis_site.apps.api.urls', namespace='internal_api')), - # This must be mounted before the `content` app to prevent Django - # from wildcard matching all requests to `pages/...`. - path('', include('pydis_site.apps.redirect.urls')), path('', include('django_prometheus.urls')), - - path('staff/', include('pydis_site.apps.staff.urls', namespace='staff')), ] if not settings.env("STATIC_BUILD") else [] urlpatterns = ( *NON_STATIC_PATTERNS, + + # This must be mounted before the `content` app to prevent Django + # from wildcard matching all requests to `pages/...`. + path('', include('pydis_site.apps.redirect.urls')), + path('pages/', include('pydis_site.apps.content.urls', namespace='content')), path('resources/', include('pydis_site.apps.resources.urls')), path('events/', include('pydis_site.apps.events.urls', namespace='events')), path('', include('pydis_site.apps.home.urls', namespace='home')), ) + + +if not settings.env("STATIC_BUILD"): + urlpatterns += ( + path('staff/', include('pydis_site.apps.staff.urls', namespace='staff')), + ) |