fix(console): normalize duplicated preview URL prefixes#3355
fix(console): normalize duplicated preview URL prefixes#3355Prince-liu wants to merge 1 commit intoagentscope-ai:mainfrom
Conversation
|
Hi @Prince-liu, thank you for your first Pull Request! 🎉 📋 About PR TemplateTo help maintainers review your PR faster, please make sure to include:
Complete PR information helps speed up the review process. You can edit the PR description to add these details. 🙌 Join Developer CommunityThanks so much for your contribution! We'd love to invite you to join the official QwenPaw developer group! You can find the Discord and DingTalk group links under the "Developer Community" section on our docs page: We truly appreciate your enthusiasm—and look forward to your future contributions! 😊 We'll review your PR soon. |
|
Repro on my local Windows setup (QwenPaw 1.1.1b1):
Before patch:
After patch:
Also verified normal path behavior remains unchanged. |
There was a problem hiding this comment.
Pull request overview
This PR updates the file preview endpoint to be more tolerant of malformed/duplicated preview URLs by normalizing the incoming filepath before resolving it to a local file on disk.
Changes:
- URL-decodes the
filepathparameter before filesystem resolution. - Strips duplicated
api/files/preview/prefixes from the path (to tolerate clients that re-prepend the preview route). - Normalizes Windows-style
/C:/...intoC:/...to improve cross-platform file lookup.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| normalized = unquote(filepath) | ||
|
|
||
| # Tolerate duplicated preview prefix from some clients, e.g. | ||
| # /api/files/preview/api/files/preview/C%3A/Users/... | ||
| while True: | ||
| trimmed = normalized.lstrip("/") | ||
| prefix = "api/files/preview/" | ||
| if trimmed.startswith(prefix): | ||
| normalized = trimmed[len(prefix) :] | ||
| continue | ||
| break | ||
|
|
||
| # Normalize /C:/... to C:/... on Windows. | ||
| if ( | ||
| len(normalized) >= 4 | ||
| and normalized[0] == "/" | ||
| and normalized[2] == ":" | ||
| and normalized[1].isalpha() | ||
| ): | ||
| normalized = normalized[1:] | ||
|
|
||
| path = Path(normalized) | ||
| if not path.is_absolute(): | ||
| path = Path("/" + filepath) | ||
| path = Path("/" + normalized) | ||
| path = path.resolve() | ||
| if not path.is_file(): |
| normalized = unquote(filepath) | ||
|
|
||
| # Tolerate duplicated preview prefix from some clients, e.g. | ||
| # /api/files/preview/api/files/preview/C%3A/Users/... | ||
| while True: | ||
| trimmed = normalized.lstrip("/") | ||
| prefix = "api/files/preview/" | ||
| if trimmed.startswith(prefix): | ||
| normalized = trimmed[len(prefix) :] | ||
| continue | ||
| break | ||
|
|
||
| # Normalize /C:/... to C:/... on Windows. | ||
| if ( | ||
| len(normalized) >= 4 | ||
| and normalized[0] == "/" | ||
| and normalized[2] == ":" | ||
| and normalized[1].isalpha() | ||
| ): | ||
| normalized = normalized[1:] | ||
|
|
||
| path = Path(normalized) | ||
| if not path.is_absolute(): | ||
| path = Path("/" + filepath) | ||
| path = Path("/" + normalized) | ||
| path = path.resolve() |

Summary
filepathin file preview API to tolerate duplicatedapi/files/preview/prefixes./C:/...paths toC:/...for robust file lookup.Why
Some messages/clients may already contain a preview URL path (
/api/files/preview/...). If another layer prepends the same prefix again, backend currently resolves an invalid filesystem path and returns404.Reproduction
/api/files/preview/api/files/preview/C%3A/Users/.../image.jpg404 Not Found.Verification
/api/files/preview/C%3A/Users/.../image.jpgScope