Slack integration: links on self-hosted domains never unfurl (parseCapShareUrl only accepts cap.so / cap.link)
维护者通常 1 天内回复
@mangeshraut712 已经在做这个了。
开始于 2026年10月14日。
评估
- 难度
- 2/5
- 预计耗时
- 1-3 小时
- 新手友好度
- 72/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 技术栈
- nextjs, typescript
调研方向
从 apps/web/lib/oembed.ts 中的 parseCapShareUrl 开始,processSlackEvent 和 /api/oembed 都会调用它,然后检查 apps/web 其他位置是如何读取 serverEnv().WEB_URL 的。确认在非 cap.so 主机上的 /s/<id> 链接目前会返回 null。当配置的 WEB_URL 主机上的分享链接在两条路径中都能解析为视频 ID,并且其他主机上的链接仍返回 null 时,即完成。
由索引模型根据 Issue 内容生成。
描述
Description
On a self-hosted Cap server, the Slack integration never shows a preview or inline player for share links on the server's own domain.
The Slack app installs and connects fine, Slack sends link_shared events, and /api/integrations/slack/events returns 200, but Cap never calls chat.unfurl. Nothing is logged, so it fails silently.
Expected: a public link like https://video.example.com/s/<id> unfurls in Slack with the title, thumbnail and inline player, the same as cap.so links.
Actual: Slack shows a plain link. Because the app claims the domain, Slack also skips its own Open Graph preview, so it's worse than having no app installed.
Cause: processSlackEvent passes each link through parseCapShareUrl (apps/web/lib/oembed.ts), which only accepts Cap's hosted domains:
if (hostname === "cap.so" && segments.length === 2 && segments[0] === "s") {
videoId = segments[1];
}
if (hostname === "cap.link" && segments.length === 1 && segments[0] !== "video") {
videoId = segments[0];
}
For any other host it returns null, so the link is dropped before the video is looked up. /api/oembed uses the same function, so it returns 400 for the server's own links, even though the share page advertises that oEmbed URL.
Suggested fix: also accept the host of WEB_URL with the /s/<id> path:
const webHost = new URL(serverEnv().WEB_URL).hostname.toLowerCase().replace(/^www\./, "");
if ((hostname === "cap.so" || hostname === webHost) && segments.length === 2 && segments[0] === "s") {
videoId = segments[1];
}
This fixes both Slack unfurls and /api/oembed on self-hosted servers.
Reproduction
- Run Cap self-hosted with
WEB_URL=https://video.example.com(officialcap-webDocker image). - Create a Slack app from
apps/web/slack-app-manifest.json, replacingcap.sowithvideo.example.comin the unfurl domain, redirect URL and event URL. - Set
SLACK_CLIENT_ID,SLACK_CLIENT_SECRETandSLACK_SIGNING_SECRET, restart cap-web, and verify the event URL in Slack (it verifies). - In Cap: Organization Settings → Integrations → Slack → Connect (it connects).
- Use a public video with no password; the organization has no access email domain.
- Paste
https://video.example.com/s/<id>in a Slack channel. - No preview appears. The server receives the Slack event (200), and Slack never loads
/embed/<id>.
Quick check without Slack:
curl -s -o /dev/null -w "%{http_code}\n" \
"https://video.example.com/api/oembed?url=https%3A%2F%2Fvideo.example.com%2Fs%2F<id>&format=json"
# returns 400 (expected 200 with oEmbed JSON)
Additional Context
- Cap version: official
ghcr.io/capsoftware/cap-webDocker image built 2026-09-07 (arm64sha256:5b65d137f7f7ddd767e1acb37380a4609f43287458410515a013157b56cfa83d). The sameparseCapShareUrlcode is onmaintoday. - Operating system, version: server is Linux arm64 (AWS ECS Fargate), self-hosted with Aurora MySQL and S3,
NEXT_PUBLIC_IS_CAPnot set. Slack desktop app on macOS. - Device (optional): n/a (server-side issue)
- Related: #2058 (Slack integration), #2122 / #2123 (share metadata on custom domains). Those fixed the Open Graph tags; this is the separate Slack-app path.
- 主要语言
- Rust
- 星标
- 23.2k
- 派生
- 2k
- 平均合并
- 1 天 10 小时
- 30 天内合并 PR
- 100
环境准备
- 提供 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
CapSoftware/Cap 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 68/100
CapSoftware/Cap#2384 · 1 条评论 ·
维护者通常 1 天内回复
-
Dashboard pagination causes full page reloads on self-hosted Cap可能已有人在做 @Dewin 于 27 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 88/100
CapSoftware/Cap#2305 · 2 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 68/100
CapSoftware/Cap#1714 · 3 条评论 ·
维护者通常 1 天内回复
-
perf: investigate redundant caption lookup passes during rendering可能已有人在做 @KrishCodesw 于 1 天前认领。 未关闭
难度 4/5 3-5 天 新手友好度 25/100
CapSoftware/Cap#2523 · 1 条评论 ·
维护者通常 1 天内回复
-
GPUI playback hitches during background edits on long recordings可能已有人在做 @AksharP5 于 1 天前认领。 未关闭
难度 3/5 半天 新手友好度 45/100
CapSoftware/Cap#2506 · 1 条评论 ·
维护者通常 1 天内回复
相似的 Issue
-
RUSTSEC-2026-0348: Brotli certificate decompression can allocate up to 1 GiB before authentication未关闭
难度 2/5 1-3 小时 新手友好度 60/100
-
难度 1/5 1-3 小时 新手友好度 62/100
-
core: Amount::from_str panics on values above 21M BTC instead of returning an error可能已有人在做 @bhuvan-somisetty 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 82/100
维护者通常 1 天内回复
-
crate: spate-s3
难度 2/5 半天 新手友好度 62/100
维护者通常 1 天内回复
-
write_iceberg ignores the table's write.parquet.compression-codec property可能已有人在做 @YuangGao 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 82/100
Eventual-Inc/Daft#7606 ·
维护者通常 1 天内回复