]> git.ipfire.org Git - pbs.git/commitdiff
api: Server mirror lists
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 3 Jul 2025 08:08:55 +0000 (08:08 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 3 Jul 2025 08:08:55 +0000 (08:08 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/api/distros.py

index 1a100678981a6717ffbf2c110e4ffee056d04705..bd2c07a75e6f8b720869929a6b0d4e24ffb98228 100644 (file)
 ###############################################################################
 
 import fastapi
+import ipaddress
+import pakfire
+import pydantic
 import typing
 
 from . import apiv1
+from . import app
 from . import backend
+from .downloads import get_current_address
 
 from ..distros import Distro
 from ..repos import Repo
@@ -94,5 +99,54 @@ async def get_repo(repo = fastapi.Depends(get_repo_from_path)) -> Repo:
        # Return the repository
        return repo
 
+# Mirror Lists
+
+class MirrorItem(pydantic.BaseModel):
+       # URL
+       url: str
+
+       # Location
+       location: str | None = None
+
+class MirrorList(pydantic.BaseModel):
+       # Type
+       type: str = "mirrorlist"
+
+       # Version
+       version: int = 1
+
+       # Mirrors
+       mirrors: list[MirrorItem]
+
+@app.get("/distros/{distro}/repos/{repo}/mirrorlist", include_in_schema=False)
+async def get_mirrorlist(
+       arch: str,
+       repo = fastapi.Depends(get_repo_from_path),
+       current_address: ipaddress.IPv6Address | ipaddress.IPv4Address = fastapi.Depends(get_current_address),
+) -> MirrorList:
+       # Check if we support the architecture
+       if not arch in pakfire.supported_arches():
+               raise fastapi.HTTPException(400, "Unsupported architecture: %s" % arch)
+
+       # Collect all suitable mirrors if the repo is mirrored
+       if repo.mirrored:
+               mirrors = [
+                       {
+                               "url"      : mirror.make_url("repos", repo.path, arch),
+                               "location" : mirror.country_code,
+                       }
+                       for mirror in await backend.mirrors.get_mirrors_for_address(current_address)
+               ]
+
+       # Otherwise we return just the base mirror
+       else:
+               mirrors = [
+                       {
+                               "url" : repo.download_url.replace("%{arch}", arch),
+                       }
+               ]
+
+       return MirrorList(mirrors=mirrors)
+
 # Add everything to the APIv1
 apiv1.include_router(router)