Repository navigation
feat: richText resource extraction and download_file_to_file - #4
Merged
haofeng0705 merged 3 commits intoSep 20, 2026
Conversation
- normalize: richText picture/file segments now extract into IncomingMessage.resources. Defensive narrowing via isinstance checks; unknown/dirty segments are skipped without affecting the rest; download codes deduped per message. - DingTalkChannel.download_file_to_file: streaming download to a local path (64 KiB chunks, no whole-file buffering), SSRF-guarded like download_file, same-dir temp file + atomic os.replace, parent dir must exist, no partial file left behind. Returns bytes written. - Tests: resource extraction/dedup/dirty-data; streaming download success, missing-parent-dir, and SSRF-block regressions.
…m lark channel-sdk - normalize: richText picture/file segments now extract into IncomingMessage.resources (analog of lark's post attachment zone). Defensive narrowing via isinstance checks; unknown/dirty segments are skipped without affecting the rest; download codes deduped per message. - DingTalkChannel.download_file_to_file: streaming download to a local path (64 KiB chunks, no whole-file buffering), SSRF-guarded like download_file, same-dir temp file + atomic os.replace, parent dir must exist, no partial file left behind. Returns bytes written. - Tests: resource extraction/dedup/dirty-data; streaming download success, missing-parent-dir, and SSRF-block regressions.
haofeng0705
requested changes
Sep 20, 2026
haofeng0705
left a comment
Contributor
There was a problem hiding this comment.
复查结论:请求修改,当前不建议合入。
- 阻塞
normalize/converters/richtext.py:33从item[\"picture\"]读取 richText 图片下载码;真实回调使用downloadCode/pictureDownloadCode,当前测试使用了错误字段。 - 阻塞
channel.py:231-245只校验初始 URL,urlopen自动跟随重定向,重定向目标未重新校验;已复现公网 URL 重定向后读取回环地址。 - 阻塞
channel.py:247-252未验证Content-Length/响应完整性,服务提前 EOF 时仍会用截断文件覆盖原目标;已复现。 channel.py:264中取消协程不会停止to_thread下载,调用方收到CancelledError后后台线程仍可能覆盖目标文件。- 项目声明支持 Python 3.8,但
asyncio.to_thread需要 Python 3.9+。
正常下载和 HTTP 500 路径已做定向验证;完整 pytest 因基线缺少 websockets 依赖未能执行。请修复以上问题并补充对应回归测试后再合入。
…le_to_file - Support downloadCode and pictureDownloadCode with fallback to picture for richText images - Use POST with JSON body for messageFiles/download in reply - Prevent SSRF redirect bypass with custom HTTPRedirectHandler - Check Content-Length to prevent overwriting with truncated files on early EOF - Add cancellation check to prevent background thread overwriting target - Provide to_thread compatibility helper for Python 3.8 - Add websockets to dependencies - Add GitHub Actions CI workflow Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
haofeng0705
approved these changes
Sep 20, 2026
haofeng0705
left a comment
Contributor
There was a problem hiding this comment.
复查通过。
- richText 图片字段已兼容
downloadCode/pictureDownloadCode/picture(src/dingtalk_channel_sdk/normalize/converters/richtext.py:32-37)。 - SSRF 重定向绕过已修复:
_SSRFSafeRedirectHandler.redirect_request逐跳校验(src/dingtalk_channel_sdk/channel.py:46-53),测试覆盖。 - 截断响应检测:流式下载在
Content-Length存在时校验实际写入字节数(src/dingtalk_channel_sdk/channel.py:270-286)。 - 取消后覆盖问题已修复:通过
threading.Event在写入前后检查取消状态(src/dingtalk_channel_sdk/channel.py:256-306)。 - Python 3.8 兼容性:新增
compat.to_thread替代asyncio.to_thread(src/dingtalk_channel_sdk/compat.py)。 pyproject.toml已补齐websockets依赖和pytest-asynciodev 依赖。- 新增 CI workflow(Python 3.8-3.12)。
pytest本地 116/116 通过。
可合入。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
为钉钉 richText 消息补齐两项媒体能力:
1. richText 附件资源提取
richText 消息中的 picture/file 段此前被解析器直接丢弃,现在提取进
IncomingMessage.resources:{"type": "image", "downloadCode": ...}{"type": "file", ...}2. DingTalkChannel.download_file_to_file(流式落盘)
流式下载文件到本地路径,不整块载入内存(64 KiB 分块):
download_file完全一致(ssrf_allowlist 白名单语义不变)os.replace,失败不落半截文件验证
pytest:113 个测试全部通过(含新增:资源提取/去重/脏数据、流式落盘成功/父目录缺失/SSRF 拦截)。与 #2 互不冲突,可任意顺序合并。