From 8a26a4ccf9069dd498317439e654e2b58bfad6c2 Mon Sep 17 00:00:00 2001 From: richjohnrambo Date: Wed, 14 Oct 2026 15:22:46 +0800 Subject: [PATCH] fix production attachment file origin --- .gitea/workflows/deploy.yml | 1 + Dockerfile | 5 +++++ README.md | 7 ++++++- web/src/lib/api/client.ts | 7 ++++++- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index eef6e580..579cd23f 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -27,6 +27,7 @@ jobs: run: | docker build \ --build-arg TINODE_API_KEY="${{ secrets.TINODE_API_KEY }}" \ + --build-arg TINODE_FILE_BASE="https://api.118im.com/v0/file" \ -t git.118im.com/im_team/im-webapp:${{ steps.vars.outputs.tag }} . docker push git.118im.com/im_team/im-webapp:${{ steps.vars.outputs.tag }} diff --git a/Dockerfile b/Dockerfile index 7f3dd3ca..683f0ae4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,6 +14,11 @@ COPY web/. . ARG TINODE_API_KEY= ENV VITE_TINODE_API_KEY=$TINODE_API_KEY +# File downloads must use the canonical IM API origin. The web origin has its own independently +# deployed path router and may otherwise send /v0/file requests to an older IM server. +ARG TINODE_FILE_BASE=https://api.118im.com/v0/file +ENV VITE_TINODE_FILE_BASE=$TINODE_FILE_BASE + RUN npm run build # ---- Stage 2: serve with nginx ---- diff --git a/README.md b/README.md index 46341f45..7f6f1ed2 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,14 @@ npm run build 根目录 `Dockerfile` 只复制并构建 `web/`: ```bash -docker build --build-arg TINODE_API_KEY="<部署密钥>" -t im-webapp . +docker build \ + --build-arg TINODE_API_KEY="<部署密钥>" \ + --build-arg TINODE_FILE_BASE="https://api.118im.com/v0/file" \ + -t im-webapp . ``` +生产环境通过 `TINODE_FILE_BASE` 固定附件下载入口;本地开发不设置该变量时,继续使用租户解析结果和 Vite 代理。 + 测试集群通过 Gitea Actions 的 `Deploy im-webapp (k3s test cluster)` 工作流手动发布。 ## 目录 diff --git a/web/src/lib/api/client.ts b/web/src/lib/api/client.ts index 3ec09e4b..5b01ea0b 100644 --- a/web/src/lib/api/client.ts +++ b/web/src/lib/api/client.ts @@ -12,6 +12,7 @@ import { useSessionStore } from '@/stores/session'; const DEFAULT_API_BASE = '/v1/im'; const DEFAULT_FILE_BASE = '/v0/file'; +const CONFIGURED_FILE_BASE = import.meta.env.VITE_TINODE_FILE_BASE?.trim(); export class ImApiError extends Error { reason?: string; @@ -123,7 +124,11 @@ export function apiBase(): string { export function fileBase(): string { const endpoints = useSessionStore.getState().tenant?.endpoints; - return (endpoints?.file || DEFAULT_FILE_BASE).replace(/\/$/, ''); + // Production may expose the web UI and the IM API through different deployments. Prefer the + // build-time canonical file origin so a tenant context previously resolved through the web host + // cannot keep routing attachments to that host's stale /v0/file proxy. Local development leaves + // this unset and continues to use the resolved relative endpoint through Vite's proxy. + return (CONFIGURED_FILE_BASE || endpoints?.file || DEFAULT_FILE_BASE).replace(/\/$/, ''); } export function currentTenantCode(): string {