Skip to content

fix(im): render resource:// images in IM channels (nginx /r/ + config guards) - #2352

Merged
lyingbug merged 1 commit into
Tencent:mainfrom
voidkey:fix/im-image-r-route-and-external-url
Jul 28, 2026
Merged

fix(im): render resource:// images in IM channels (nginx /r/ + config guards)#2352
lyingbug merged 1 commit into
Tencent:mainfrom
voidkey:fix/im-image-r-route-and-external-url

Conversation

@voidkey

@voidkey voidkey commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Description

IM channels (DingTalk / Feishu / etc.) rendered blank/broken images when an answer contained knowledge‑base images. These images are carried as resource://<handle> references that resolve to WeKnora capability links (<APP_EXTERNAL_URL>/r/<token>), which were neither reachable nor rendered:

  • nginx never proxied /r/. /r/<token> links fell through into the SPA try_files … /index.html fallback and returned a blank HTML page, so the image never loaded. This is the root cause of the reported issue.
  • rewriteStorageURLs treated any dst != src as success. When APP_EXTERNAL_URL was unset, a resource:// alias could resolve to an internal storage://… path, which was then emitted verbatim to the IM client (unfetchable).
  • The configuration requirement was undocumented and silent, so operators had no signal about why images broke.

Changes

  • frontend/nginx.conf: add a location ^~ /r/ proxy block mirroring /files and /api/ (same ${APP_SCHEME}/${APP_HOST}/${APP_PORT} vars and forwarding headers), so capability links reach the backend instead of the SPA fallback.
  • internal/im/service.go: only substitute an http(s) result in rewriteStorageURLs (via isHTTPResolvedURL, case‑insensitive per RFC 3986); otherwise leave the reference unchanged and log an actionable WARN. Add a one‑time startup WARN when IM channels are active but APP_EXTERNAL_URL is unset — the config state that silently breaks resource:// images on the default MinIO/local deployment.
  • Docs (.env.example, docker-compose.yml, docs/IM集成开发文档.md): document that IM knowledge‑base images need an IM‑reachable HTTP URL via one of two paths — (A) a publicly reachable storage backend (e.g. object storage with a public endpoint, or MINIO_ENDPOINT set to a public host), or (B) set APP_EXTERNAL_URL so resource:// routes through nginx /r/. The default MinIO deployment (internal minio:9000) uses path (B).

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 📚 Documentation update
  • 🎨 Refactor
  • ⚡ Performance improvement
  • 🧪 Test
  • 🔧 Configuration / Build / CI

Related Issue

Fixes #2277

Testing

  • Added unit tests: TestRewriteStorageURLs_NonHTTPResultIsNoOp and TestRewriteStorageURLs_UppercaseSchemeIsSubstituted (guard behavior), and TestIMImageConfigWarning (startup warning matrix).
  • gofmt -l, go vet ./internal/im/, go build ./internal/im/..., and go test ./internal/im/ all pass locally. The change is IM‑scoped; the full make test suite was not run locally.
  • Verified the fix is orthogonal to recent upstream IM lifecycle work: rebased onto latest main with no conflicts; our changes (URL rewrite + startup config warning) touch a different code region than the connection‑lifecycle refactors.

Checklist

  • gofmt / go vet / go build / go test ./internal/im/ pass locally (full make test not run — change is IM‑scoped)
  • Self-reviewed the code
  • Added/updated tests covering the change
  • Updated related documentation (.env.example, docker-compose.yml, docs/)
  • Breaking changes are clearly called out in the description above (none)

… guards)

IM channels (DingTalk/Feishu) showed broken images because resource://
image references resolve to WeKnora capability links that were neither
reachable nor renderable:

- nginx never proxied /r/, so <APP_EXTERNAL_URL>/r/<token> links fell into
  the SPA fallback and returned a blank page. Add a /r/ proxy block
  mirroring /files, using the ${APP_SCHEME}/${APP_HOST}/${APP_PORT} vars.
- rewriteStorageURLs treated any "dst != src" as success and emitted
  non-HTTP results (e.g. an internal storage:// path when APP_EXTERNAL_URL
  is unset) that IM clients cannot fetch. Only substitute http(s) URLs;
  otherwise leave the reference unchanged and log an actionable WARN.
- Warn once at startup when IM channels are active but APP_EXTERNAL_URL is
  unset — the config state that silently breaks resource:// images on the
  default MinIO/local deployment.
- Document that IM knowledge-base images need an IM-reachable http URL via
  one of two paths: a publicly reachable storage backend, or APP_EXTERNAL_URL
  routing resource:// through nginx /r/.
@lyingbug
lyingbug merged commit 4e3b512 into Tencent:main Jul 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: IM渠道钉钉,更新到最新版后图片无法加载,web正常

2 participants