mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-21 09:28:14 +00:00
web 插件讲解
网络工具插件,提供网页搜索和内容抓取功能。
工具清单
| 工具 | 功能 | 源码 |
|---|---|---|
web_search |
通过 DuckDuckGo 搜索网页 | handleSearch |
web_fetch |
抓取指定 URL 的内容 | handleFetch |
核心设计
搜索实现
web_search 使用 DuckDuckGo 的 HTML 搜索页面(非 API,免注册):
// plugin.go:handleSearch
url := fmt.Sprintf("https://html.duckduckgo.com/html/?q=%s", url.QueryEscape(query))
resp, err := p.httpClient().Get(url)
解析策略:扫描 HTML 查找 <a class="result__a" 标签提取标题和链接,查找 <a class="result__snippet" 提取摘要。搜索最多返回 8 条结果。
由于 DuckDuckGo 在国内被墙,支持通过代理访问(见配置项)。
页面抓取
web_fetch 直接 HTTP GET 目标 URL 并以文本形式返回内容:
// plugin.go:handleFetch
resp, err := p.httpClient().Get(rawURL)
body, _ := io.ReadAll(resp.Body)
返回内容限制最大 100KB,超过截断并提示。
SSRF 防护
handleFetch 检查 URL 是否为内网 IP,防止服务端请求伪造攻击:
// plugin.go:handleFetch — SSRF guard
if !strings.HasPrefix(parsedURL, "http") {
return errorResult("only http/https allowed"), nil
}
// 内网 IP 段检查(127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
HTTP 客户端
newHTTPClient() 创建带超时和可选代理的 HTTP 客户端:
// plugin.go:newHTTPClient
func (p *Plugin) newHTTPClient() *http.Client {
transport := &http.Transport{}
if p.proxy != "" {
proxyURL, _ := url.Parse(p.proxy)
transport.Proxy = http.ProxyURL(proxyURL)
}
return &http.Client{
Timeout: time.Duration(p.timeout) * time.Second,
Transport: transport,
}
}
超时和代理均在配置中设置。
配置读取
// plugin.go:Start
p.timeout = getSetting[float64](s.Settings(), "timeout", 30)
p.proxy = getSetting[string](s.Settings(), "proxy", "")
getSetting 是泛型辅助函数,支持类型安全的配置读取。
配置项
| Key | 默认值 | 说明 |
|---|---|---|
plugin.web.timeout |
30 |
HTTP 请求超时(秒) |
plugin.web.proxy |
空 | HTTP 代理地址,如 http://<proxy-host>:<proxy-port> |
注意事项
- DuckDuckGo HTML 格式可能随网站更新变化,如果搜索结果解析失败需调整
parseSearchResults中的 HTML 标记匹配 - SSRF 防护默认阻止内网请求,如需访问内网资源需修改
isInternalIP逻辑 - 搜索结果依赖 DuckDuckGo 可用性,在国内使用建议配置代理