fix legacy attachment URLs in Vite web

This commit is contained in:
richjohnrambo
2026-10-14 13:58:33 +08:00
parent 0570f2c5bd
commit ec22b709b5
3 changed files with 66 additions and 2 deletions
+27
View File
@@ -0,0 +1,27 @@
/**
* Older clients persisted attachment refs on the API host, for example
* `https://api.example.com/v0/file/s/...`. Fetching those URLs with the file
* auth headers makes the browser forward a CORS preflight through the OSS
* redirect. Route them through the tenant's configured file endpoint instead,
* matching the relative refs emitted by current clients.
*/
export function normalizeFileDownloadUrl(
refUrl: string,
apiEndpoint: string,
fileEndpoint: string,
pageOrigin: string,
): string {
try {
const source = new URL(refUrl, pageOrigin);
const api = new URL(apiEndpoint, pageOrigin);
if (source.origin !== api.origin || !source.pathname.startsWith('/v0/file/')) return refUrl;
const target = new URL(fileEndpoint, pageOrigin);
target.pathname = target.pathname.replace(/\/$/, '') + source.pathname.slice('/v0/file'.length);
target.search = source.search;
target.hash = source.hash;
return target.toString();
} catch {
return refUrl;
}
}
+5 -2
View File
@@ -9,7 +9,8 @@
// at all -- so this hand-built fetch, not the SDK helper, is the only path that actually works here).
import { API_KEY } from '@/lib/config';
import { authToken, fileBase } from './client';
import { apiBase, authToken, fileBase } from './client';
import { normalizeFileDownloadUrl } from './file-url';
import { getTinode } from '../tinode/connection';
/** Confirmed live: the real `ctrl.params` shape is `{file_id, url, expires}` -- no `name`/`size`/
@@ -98,7 +99,9 @@ export function upgradeToHttps(url: string): string {
* fileBase() down to just its origin before appending, rather than concatenating the two paths.
*/
export function fileDownloadUrl(refUrl: string): string {
if (refUrl.startsWith('http')) return upgradeToHttps(refUrl);
if (refUrl.startsWith('http')) {
return upgradeToHttps(normalizeFileDownloadUrl(refUrl, apiBase(), fileBase(), window.location.origin));
}
const origin = fileBase().replace(/\/v0\/file.*$/, '');
return `${origin}${refUrl}`;
}
+34
View File
@@ -0,0 +1,34 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { createJiti } from 'jiti';
const jiti = createJiti(import.meta.url);
const { normalizeFileDownloadUrl } = await jiti.import('../src/lib/api/file-url.ts');
const pageOrigin = 'https://web.118im.com';
const apiEndpoint = 'https://api.118im.com/v1/im';
const fileEndpoint = 'https://web.118im.com/v0/file';
test('routes historical API-host attachment refs through the configured file endpoint', () => {
assert.equal(
normalizeFileDownloadUrl(
'https://api.118im.com/v0/file/s/example.jpg?size=large#preview',
apiEndpoint,
fileEndpoint,
pageOrigin,
),
'https://web.118im.com/v0/file/s/example.jpg?size=large#preview',
);
});
test('leaves current and unrelated attachment refs unchanged', () => {
assert.equal(
normalizeFileDownloadUrl('/v0/file/s/current.jpg', apiEndpoint, fileEndpoint, pageOrigin),
'/v0/file/s/current.jpg',
);
assert.equal(
normalizeFileDownloadUrl('https://cdn.example.com/image.jpg', apiEndpoint, fileEndpoint, pageOrigin),
'https://cdn.example.com/image.jpg',
);
});