fix legacy attachment URLs in Vite web
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,8 @@
|
|||||||
// at all -- so this hand-built fetch, not the SDK helper, is the only path that actually works here).
|
// 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 { 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';
|
import { getTinode } from '../tinode/connection';
|
||||||
|
|
||||||
/** Confirmed live: the real `ctrl.params` shape is `{file_id, url, expires}` -- no `name`/`size`/
|
/** 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.
|
* fileBase() down to just its origin before appending, rather than concatenating the two paths.
|
||||||
*/
|
*/
|
||||||
export function fileDownloadUrl(refUrl: string): string {
|
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.*$/, '');
|
const origin = fileBase().replace(/\/v0\/file.*$/, '');
|
||||||
return `${origin}${refUrl}`;
|
return `${origin}${refUrl}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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',
|
||||||
|
);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user