feat: add resolve_shortlink tool to extract feed_id and xsec_token from xhslink.com URLs#589
feat: add resolve_shortlink tool to extract feed_id and xsec_token from xhslink.com URLs#589zero469 wants to merge 2 commits intoxpzouying:mainfrom
Conversation
…om xhslink.com URLs - Add xiaohongshu/shortlink.go with HTTP redirect-based URL resolution - Uses mobile User-Agent to get proper 302 redirect from xiaohongshu - Extracts feed_id from path and xsec_token from query params - Register as MCP tool xpzouying#14 for direct short link parsing
|
There was a problem hiding this comment.
代码审查意见 — PR #589
📋 概述
本 PR 新增 resolve_shortlink MCP 工具,通过 HTTP 302 重定向解析小红书分享短链接(xhslink.com),提取 feed_id 和 xsec_token。功能定义清晰,实现思路合理,PR 描述完善。以下是具体的审查意见。
✅ 亮点
- 良好的关注点分离 — 核心解析逻辑放在
xiaohongshu/shortlink.go,handler / service / server 注册各司其职,符合项目分层架构。 - 安全的重定向处理 — 使用
CheckRedirect禁止自动跟随重定向,手动提取Locationheader,避免不必要的请求泄露。 - 域名白名单校验 —
normalizeShortLinkURL对输入域名做了校验,防止 SSRF 风险。 - PR 描述 — 包含 Summary / Changes / Usage / Testing 各项,信息充分。
🔍 需改进的问题
1. 🔴 正则在函数内重复编译(性能问题)
extractFeedIDFromPath 每次调用都会 regexp.MustCompile 编译 3 个正则表达式。虽然项目中其他地方也有类似写法,但这是一个已知的反模式。建议提升到包级变量:
var (
feedIDPatterns = []*regexp.Regexp{
regexp.MustCompile(`/discovery/item/([a-zA-Z0-9]+)`),
regexp.MustCompile(`/explore/([a-zA-Z0-9]+)`),
regexp.MustCompile(`/note/([a-zA-Z0-9]+)`),
}
)2. 🔴 Handler 函数签名与项目主流模式不一致
项目中大多数 handler 接收 map[string]interface{} 或 typed struct args,例如 handleSearchFeeds(ctx, args SearchFeedsArgs)。而此 PR 中的 handleResolveShortLink 接收 string:
func (s *AppServer) handleResolveShortLink(ctx context.Context, shortURL string) *MCPToolResult这意味着参数提取和验证被拆分到两个地方(handler 校验空字符串,但 MCP server 层拆解 args.URL)。建议统一为:
func (s *AppServer) handleResolveShortLink(ctx context.Context, args ResolveShortLinkArgs) *MCPToolResult {
if args.URL == "" {
// ...
}
// ...
}这样也与 handleSearchFeeds 的 typed struct 模式一致。
3. 🟡 xsec_token 被打印到日志中(安全隐患)
logrus.Infof("解析成功: feed_id=%s, xsec_token=%s", feedID, xsecToken)xsec_token 是一个令牌类参数,完整打印在日志中可能存在安全风险。建议移除或脱敏处理:
logrus.Infof("解析成功: feed_id=%s", feedID)4. 🟡 缺少单元测试
PR 描述中提到"单元测试通过"和"端到端测试通过",但 diff 中没有包含任何 *_test.go 文件。normalizeShortLinkURL、parseRedirectURL、extractFeedIDFromPath 都是纯函数,非常适合编写表驱动单元测试。建议至少补充 shortlink_test.go。
5. 🟡 HTTP Client 未复用
每次调用 ResolveShortLink 都会新建一个 http.Client。虽然 Go 的 http.Client 创建成本不高,但内部的 Transport 连接池无法跨请求复用。如果短时间内频繁调用,建议将 client 提升为包级变量或注入到 service 中:
var shortLinkClient = &http.Client{
Timeout: 10 * time.Second,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}6. 🟢 comment_feed.go 的空白字符修改
xiaohongshu/comment_feed.go 的修改仅为行尾空白清理(trailing whitespace),不影响功能。建议在单独的 commit 中处理此类格式化修改,保持功能 PR 的 diff 干净。
💡 其他建议(非阻塞)
- 支持更多状态码: 除 301/302 外,小红书可能返回 307/308 重定向,可考虑扩展
resp.StatusCode的判断范围。 - 超时可配置: 当前硬编码
10 * time.Second,可考虑从 context 或配置中获取。 - 输入容错: 用户可能粘贴包含中文字符或额外文本的链接(如
「小红书笔记」https://xhslink.com/xxx),可在normalizeShortLinkURL中增加 URL 提取逻辑。
📊 总结
| 维度 | 评价 |
|---|---|
| 功能完整性 | ⭐⭐⭐⭐ 功能清晰完整 |
| 代码质量 | ⭐⭐⭐ 整体良好,有几处可改进 |
| 安全性 | ⭐⭐⭐ 有域名白名单,但 token 日志需处理 |
| 测试 | ⭐⭐ 缺少测试文件 |
| 一致性 | ⭐⭐⭐ 基本遵循项目模式,handler 签名需对齐 |
建议: 请解决 🔴 标记的问题后合并。🟡 问题建议修复但非阻塞。
🤖 由 Kimi Code Agent 自动审查
|
Now let me look at the existing code patterns to understand the codebase conventions:
Be thorough and report back specific code examples. 主要发现🔴 需修复(2 项):
🟡 建议改进(3 项): 🟢 非阻塞: |
- Move regex patterns to package-level vars (avoid recompilation) - Reuse HTTP client with connection pool - Handler now accepts ResolveShortLinkArgs struct (consistent with other handlers) - Remove xsec_token from logs (security)
|
感谢 @kimi-agent-bot 的详细审查!已在最新 commit 中解决所有问题: 🔴 已修复
🟡 已修复
🟢 说明
Commit: |
|
|
@zero469 感谢快速修复!已逐项核对最新 commit
代码质量 LGTM 👍,从我这边来看没有其他阻塞问题了。
|
|
已确认最新 diff 中的修复情况,下面逐项验证: ✅ 正则提升为包级变量 — ✅ Handler 签名统一 — ✅ xsec_token 已从日志移除 — 日志仅保留 ✅ HTTP Client 复用 — 一切就绪,发布确认评论: |
|
@xpzouying 请求 review,已解决 Kimi bot 的所有审查意见 🙏 |
Summary
resolve_shortlinkMCP 工具,可从小红书分享短链接(xhslink.com)直接提取feed_id和xsec_tokenChanges
ResolveShortLink服务方法resolve_shortlinkhandleResolveShortLink处理函数Usage
输入:
http://xhslink.com/o/1kZVDhZks0n输出:
{ "feed_id": "69ba1706000000001a023daf", "xsec_token": "CBc35g8tRNZgaxC5icq1yawooXNOzVHw8ke6PGldcYa8U=", "original_url": "https://xhslink.com/o/1kZVDhZks0n", "redirect_url": "https://www.xiaohongshu.com/discovery/item/...", "share_id": "f5d4aabc8e014cce9d331b372eb94a22", "app_platform": "ios", "xsec_source": "app_share" }Testing
go build编译通过