Redirects.Py
Creates redirects for times when your backend server can't.
Configuration
Enable the redirect hook by adding it to your list of hooks.
[markata] # Were you keep static assets to copy into the project, default is static # the assets_dir will set the default _redirects file directory assets_dir = "static" # You can override the default redirects file location redirects = static/_redirects hooks = [ # creates redirects from static/_redirects file "markata.plugins.redirects", # copies your static assets into the output_dir (default: `markout`) "markata.plugins.copy_assets", ... ]
Syntax
Your _redirects
file is a simplified version of what services like cloudflare
pages or netlify use. In fact you can use the same redirects file!
Here is an example that will redirect /old
to /new
and /CHANGELOG
to
/changelog
/old /new /CHANGELOG /changelog
Limitations
no splats
Since it is static generated this plugin cannot cover *'s. * or splat redirects need to be taken care of server side. It also cannot change the http code, this is only
Features
The features of markata.plugins.redirect is pretty limited since it is implemented only as a static page. Other features require server side implementation.
Feature | Support | Example | Notes |
---|---|---|---|
Force | Yes | /pagethatexists /otherpage |
Creates an index.html with http-equiv and canonical |
Redirects (301, 302, 303, 307, 308) | No | /home / 301 |
Ignored, requires server side implementation |
Rewrites (other status codes) | No | /blog/* /blog/404.html 404 |
... |
Splats | No | /blog/* /blog/:splat |
... |
Placeholders | No | /blog/:year/:month/:date/:slug /news/:year/:month/:date/:slug |
... |
Query Parameters | No | /shop id=:id /blog/:id 301 |
... |
Proxying | No | /blog/* https://blog.my.domain/:splat 200 |
... |
Domain-level redirects | No | workers.example.com/* workers.example.com/blog/:splat 301 |
... |
Redirect by country or language | No | / /us 302 Country=us |
... |
Redirect by cookie | No | /* /preview/:splat 302 Cookie=preview |
... |
Compare with cloudflare-pages
Tip
If you have a public site, pair this up with ahrefs to keep up with pages that have moved without you realizing.
!! class
Redirect class
DataClass to store the original and new urlRedirect source
class Redirect(pydantic.BaseModel): "DataClass to store the original and new url" original: str new: str markata: Markata model_config = ConfigDict(validate_assignment=True, arbitrary_types_allowed=True)
!! class
RedirectsConfig class
RedirectsConfig source
class RedirectsConfig(pydantic.BaseModel): assets_dir: Path = Path("static") redirects_file: Optional[Path] = None @pydantic.validator("redirects_file", always=True) def default_redirects_file( cls: "RedirectsConfig", v: Path, *, values: Dict ) -> Path: if not v: return Path(values["assets_dir"]) / "_redirects" return v
!! class
Config class
Config source
class Config(pydantic.BaseModel): redirects: RedirectsConfig = RedirectsConfig()
!! function
config_model function
config_model source
def config_model(markata: "Markata") -> None: markata.config_models.append(Config)
!! function
save function
saves an index.html in the directory called out by the redirect.save source
def save(markata: "Markata") -> None: """ saves an index.html in the directory called out by the redirect. """ redirects_file = Path(markata.config.redirects.redirects_file) if redirects_file.exists(): raw_redirects = redirects_file.read_text().split("\n") else: raw_redirects = [] redirects = [ Redirect(original=s[0], new=s[1], markata=markata) for r in raw_redirects if "*" not in r and len(s := r.split()) == 2 and not r.strip().startswith("#") ] if "redirect_template" in markata.config: template_file = Path(str(markata.config.get("redirect_template"))) else: template_file = DEFAULT_REDIRECT_TEMPLATE template = Template(template_file.read_text()) for redirect in redirects: file = markata.config.output_dir / redirect.original.strip("/") / "index.html" file.parent.mkdir(parents=True, exist_ok=True) file.write_text(template.render(redirect.dict(), config=markata.config))
!! method
default_redirects_file method
default_redirects_file source
def default_redirects_file( cls: "RedirectsConfig", v: Path, *, values: Dict ) -> Path: if not v: return Path(values["assets_dir"]) / "_redirects" return v