|
1 | 1 | import asyncio |
2 | 2 | import contextlib |
3 | 3 | import os |
| 4 | +import re |
4 | 5 | import time |
5 | 6 | from collections.abc import Callable |
6 | 7 | from io import BytesIO |
7 | 8 |
|
| 9 | +from yarl import URL |
| 10 | + |
8 | 11 | from comfy.cli_args import args |
9 | 12 | from comfy.model_management import processing_interrupted |
10 | 13 | from comfy_api.latest import IO |
11 | 14 |
|
12 | 15 | from .common_exceptions import ProcessingInterrupted |
13 | 16 |
|
| 17 | +_HAS_PCT_ESC = re.compile(r"%[0-9A-Fa-f]{2}") # any % followed by 2 hex digits |
| 18 | +_HAS_BAD_PCT = re.compile(r"%(?![0-9A-Fa-f]{2})") # any % not followed by 2 hex digits |
| 19 | + |
14 | 20 |
|
15 | 21 | def is_processing_interrupted() -> bool: |
16 | 22 | """Return True if user/runtime requested interruption.""" |
@@ -69,3 +75,17 @@ def get_fs_object_size(path_or_object: str | BytesIO) -> int: |
69 | 75 | if isinstance(path_or_object, str): |
70 | 76 | return os.path.getsize(path_or_object) |
71 | 77 | return len(path_or_object.getvalue()) |
| 78 | + |
| 79 | + |
| 80 | +def to_aiohttp_url(url: str) -> URL: |
| 81 | + """If `url` appears to be already percent-encoded (contains at least one valid %HH |
| 82 | + escape and no malformed '%' sequences) and contains no raw whitespace/control |
| 83 | + characters preserve the original encoding byte-for-byte (important for signed/presigned URLs). |
| 84 | + Otherwise, return `URL(url)` and allow yarl to normalize/quote as needed.""" |
| 85 | + if any(c.isspace() for c in url) or any(ord(c) < 0x20 for c in url): |
| 86 | + # Avoid encoded=True if URL contains raw whitespace/control chars |
| 87 | + return URL(url) |
| 88 | + if _HAS_PCT_ESC.search(url) and not _HAS_BAD_PCT.search(url): |
| 89 | + # Preserve encoding only if it appears pre-encoded AND has no invalid % sequences |
| 90 | + return URL(url, encoded=True) |
| 91 | + return URL(url) |
0 commit comments