Fix new attachement URLs

This commit is contained in:
2026-07-15 15:15:29 +03:00
Unverified
parent cd8962563e
commit d821afa66b
2 changed files with 30 additions and 5 deletions
+23 -2
View File
@@ -1,12 +1,33 @@
import { API_BASE_URL } from "@/core/config"; import { API_BASE_URL } from "@/core/config";
import { getAuthHeaders } from "./user/auth"; import { getAuthHeaders } from "./user/auth";
/**
* Resolve a server attachment path to a fetchable URL.
* Strips a legacy `/api` prefix, then joins to the API base (or same-origin `/api` in the browser).
*/
export function resolveAttachmentUrl(path: string): string {
if (/^https?:\/\//i.test(path)) return path;
let relative = path.startsWith("/") ? path : `/${path}`;
if (relative.startsWith("/api/") || relative === "/api") {
relative = relative.slice(4) || "/";
}
// Same-origin `/api` keeps Vite/Caddy proxies working for <img> + cookie auth.
if (typeof window !== "undefined" && !API_BASE_URL.startsWith("http")) {
const base = API_BASE_URL.replace(/\/$/, "") || "/api";
return `${base}${relative}`;
}
if (typeof window !== "undefined") {
return `/api${relative}`;
}
return `${API_BASE_URL.replace(/\/$/, "")}${relative}`;
}
export const normal = { export const normal = {
/** /**
* Gets the URL for a normal (unencrypted) file * Gets the URL for a normal (unencrypted) file
*/ */
url(filename: string): string { url(filename: string): string {
return `${API_BASE_URL}/uploads/files/normal/${filename}`; return resolveAttachmentUrl(`/uploads/files/normal/${filename}`);
}, },
/** /**
@@ -26,7 +47,7 @@ export const encrypted = {
* Gets the URL for an encrypted file * Gets the URL for an encrypted file
*/ */
url(filename: string): string { url(filename: string): string {
return `${API_BASE_URL}/uploads/files/encrypted/${filename}`; return resolveAttachmentUrl(`/uploads/files/encrypted/${filename}`);
}, },
/** /**
+7 -3
View File
@@ -230,7 +230,7 @@ export function Message({ message, isAuthor, onContextMenu, onReactionClick, isD
try { try {
// no-op decrypt indicator removed from UI // no-op decrypt indicator removed from UI
// Fetch encrypted file // Fetch encrypted file
const response = await fetch(file.path, { const response = await fetch(api.files.resolveAttachmentUrl(file.path), {
headers: api.user.auth.getAuthHeaders(user.authToken!) headers: api.user.auth.getAuthHeaders(user.authToken!)
}); });
if (!response.ok) throw new Error("Failed to fetch file"); if (!response.ok) throw new Error("Failed to fetch file");
@@ -425,7 +425,7 @@ export function Message({ message, isAuthor, onContextMenu, onReactionClick, isD
} }
// If not decrypted or public file, fetch with credentials/headers // If not decrypted or public file, fetch with credentials/headers
const response = await fetch(file.path, { const response = await fetch(api.files.resolveAttachmentUrl(file.path), {
headers: user.authToken ? api.user.auth.getAuthHeaders(user.authToken) : undefined, headers: user.authToken ? api.user.auth.getAuthHeaders(user.authToken) : undefined,
credentials: "include" credentials: "include"
}); });
@@ -585,7 +585,11 @@ export function Message({ message, isAuthor, onContextMenu, onReactionClick, isD
const looksEncryptedPath = /\/uploads\/files\/encrypted\//.test(file.path) || /\/api\/uploads\/files\/encrypted\//.test(file.path); const looksEncryptedPath = /\/uploads\/files\/encrypted\//.test(file.path) || /\/api\/uploads\/files\/encrypted\//.test(file.path);
const isEncryptedDm = Boolean(isDm && (file.encrypted || looksEncryptedPath)); const isEncryptedDm = Boolean(isDm && (file.encrypted || looksEncryptedPath));
const decryptedUrl = decryptedFiles.get(file.path); const decryptedUrl = decryptedFiles.get(file.path);
const imageSrc = isImage ? (isEncryptedDm ? decryptedUrl : file.path) : undefined; const imageSrc = isImage
? (isEncryptedDm
? decryptedUrl
: api.files.resolveAttachmentUrl(file.path))
: undefined;
const isDownloading = downloadingPaths.has(file.path); const isDownloading = downloadingPaths.has(file.path);
const isSending = message.runtimeData?.sendingState?.status === 'sending'; const isSending = message.runtimeData?.sendingState?.status === 'sending';