mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-06-24 00:39:30 +08:00
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>
42 lines
1.3 KiB
Python
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}"
|