fix: Go-пакеты со слешами в имени ломали роутинг

Использован :path в FastAPI-роутах, имя+версия парсятся из URL.
Шаблоны urlencode-ят имена пакетов при генерации ссылок.
This commit is contained in:
Marker689
2026-05-10 06:41:00 +03:00
parent 6523f55dcd
commit 22dc87851a
5 changed files with 22 additions and 11 deletions

View File

@@ -1,5 +1,7 @@
"""Web UI routes — Jinja2 + htmx pages."""
from urllib.parse import unquote
from fastapi import APIRouter, Depends, Request
from fastapi.responses import HTMLResponse
from jinja2 import Environment, PackageLoader, select_autoescape
@@ -154,20 +156,25 @@ async def packages_list(
)
@router.get("/packages/{name}/{version}", response_class=HTMLResponse)
@router.get("/packages/{name:path}", response_class=HTMLResponse)
async def package_detail(
name: str,
version: str,
request: Request,
session: AsyncSession = Depends(get_session),
):
# name:path captures the entire path after /packages/
# e.g. "eviltest/0.1.0" or "github.com/attacker/evilmodule/v0.1.0"
parts = name.rsplit("/", 1)
pkg_name = unquote(parts[0])
pkg_version = unquote(parts[1]) if len(parts) == 2 else ""
from sqlalchemy.orm import selectinload
scans = (
(
await session.execute(
select(Scan)
.where(Scan.package_name == name, Scan.package_version == version)
.where(Scan.package_name == pkg_name, Scan.package_version == pkg_version)
.options(selectinload(Scan.findings))
.order_by(Scan.started_at.desc())
)
@@ -185,8 +192,8 @@ async def package_detail(
return _render(
"package_detail.html",
pkg_name=name,
pkg_version=version,
pkg_name=pkg_name,
pkg_version=pkg_version,
scans=scans,
findings=all_findings,
request=request,

View File

@@ -21,7 +21,7 @@
<tbody>
{% for p in packages %}
<tr>
<td><a href="/packages/{{ p.pkg_name }}/{{ p.pkg_ver }}">{{ p.pkg_name }}</a></td>
<td><a href="/packages/{{ p.pkg_name | urlencode }}/{{ p.pkg_ver | urlencode }}">{{ p.pkg_name }}</a></td>
<td>{{ p.pkg_ver }}</td>
<td>{{ p.ecosystem }}</td>
<td>{{ p.repository }}</td>

View File

@@ -52,7 +52,7 @@
<tbody>
{% for s in latest_scans %}
<tr>
<td><a href="/packages/{{ s.package_name }}/{{ s.package_version }}">{{ s.package_name }}</a></td>
<td><a href="/packages/{{ s.package_name | urlencode }}/{{ s.package_version | urlencode }}">{{ s.package_name }}</a></td>
<td>{{ s.package_version }}</td>
<td><small>{{ s.repository }}</small></td>
<td>

View File

@@ -14,7 +14,7 @@
<article class="scan-info-block">
<div class="scan-info-grid">
<div><strong>Package</strong><br><a href="/packages/{{ scan.package_name }}/{{ scan.package_version }}">{{ scan.package_name }}</a></div>
<div><strong>Package</strong><br><a href="/packages/{{ scan.package_name | urlencode }}/{{ scan.package_version | urlencode }}">{{ scan.package_name }}</a></div>
<div><strong>Version</strong><br>{{ scan.package_version }}</div>
<div><strong>Ecosystem</strong><br>{{ scan.ecosystem }}</div>
<div><strong>Repository</strong><br>{{ scan.repository }}</div>