ComfyUI/app/model_downloader/hf_url.py
DoronGenzelHass fdd84d04a0 feat(model_downloader): server-side model download + HuggingFace OAuth subsystem
Self-contained package under app/model_downloader/:
- Allowlist + path-validated downloads (SSRF guard: HF/Civitai/localhost + model extension).
- Streaming worker: writes to <final>.tmp, atomic rename on success, cooperative cancellation with epoch-based session identity, orphan .tmp sweep.
- Unified availability probe with per-URL gated/size caching; is_hf_downloadable recomputed per call so login/license changes surface within one poll.
- HuggingFace OAuth 2.0 PKCE flow with loopback callback server and on-disk (0600) token storage + transparent refresh.
- Pydantic request/response schemas and aiohttp routes under api/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 15:16:59 +03:00

42 lines
1.3 KiB
Python

"""Parsers for the ``huggingface.co`` URL shape we accept in workflows.
The download API accepts URLs of the form
``https://huggingface.co/<org>/<repo>/resolve/<rev>/<path/to/file>``.
We need to recover ``<org>/<repo>`` (the *repo_id*) from such URLs for
``huggingface_hub`` API calls (notably ``HfApi.auth_check``).
"""
from __future__ import annotations
from typing import Optional
from urllib.parse import urlparse
_HF_HOST = "huggingface.co"
def is_hf_url(url: str) -> bool:
"""Cheap host check — does this URL point at huggingface.co?"""
try:
return urlparse(url).hostname == _HF_HOST
except ValueError:
return False
def repo_id_from_url(url: str) -> Optional[str]:
"""Extract ``<org>/<repo>`` from an HF model file URL.
Returns ``None`` if the URL isn't on huggingface.co or doesn't look
like a model-file URL. The expected shape is
``/<org>/<repo>/resolve/<rev>/<path>`` — anything else
(datasets, spaces, /tree/, /blob/, …) we treat as out of scope here.
"""
if not is_hf_url(url):
return None
parts = urlparse(url).path.lstrip("/").split("/")
if len(parts) < 4 or parts[2] != "resolve":
return None
org, repo = parts[0], parts[1]
if not org or not repo:
return None
return f"{org}/{repo}"