diff --git a/packages/backend/src/misc/fetch-meta.ts b/packages/backend/src/misc/fetch-meta.ts
index 3d66f2d63..14372a792 100644
--- a/packages/backend/src/misc/fetch-meta.ts
+++ b/packages/backend/src/misc/fetch-meta.ts
@@ -31,6 +31,11 @@ export function metaToPugArgs(meta: Meta): object {
};
}
+export function fetchMetaSync(): Meta | null {
+ return cache;
+}
+
+
export async function fetchMeta(noCache = false): Promise {
if (!noCache && cache) return cache;
diff --git a/packages/backend/src/models/repositories/drive-file.ts b/packages/backend/src/models/repositories/drive-file.ts
index 68f5f1081..4d6567e81 100644
--- a/packages/backend/src/models/repositories/drive-file.ts
+++ b/packages/backend/src/models/repositories/drive-file.ts
@@ -8,6 +8,7 @@ import config from "@/config/index.js";
import { appendQuery, query } from "@/prelude/url.js";
import { DriveFolders, Users } from "../index.js";
import { deepClone } from "@/misc/clone.js";
+import { fetchMetaSync } from "@/misc/fetch-meta.js";
type PackOptions = {
detail?: boolean;
@@ -71,14 +72,9 @@ export const DriveFileRepository = db.getRepository(DriveFile).extend({
);
}
- // リモートかつ期限切れはローカルプロキシを試みる
- if (file.uri != null && file.isLink && config.proxyRemoteFiles) {
- const key = thumbnail ? file.thumbnailAccessKey : file.webpublicAccessKey;
-
- if (key && !key.match("/")) {
- // 古いものはここにオブジェクトストレージキーが入ってるので除外
- return `${config.url}/files/${key}`;
- }
+ if (file.isLink && config.proxyRemoteFiles) {
+ const url = this.getDatabasePrefetchUrl(file, thumbnail);
+ if (url != null) return `${config.url}/proxy/${encodeURIComponent(new URL(url).pathname)}?${query({ url: url })}`;
}
return thumbnail
@@ -92,6 +88,25 @@ export const DriveFileRepository = db.getRepository(DriveFile).extend({
: file.webpublicUrl ?? file.url;
},
+ getFinalUrl(url: string): string {
+ if (!config.proxyRemoteFiles) return url;
+ if (url.startsWith(`${config.url}/files`)) return url;
+ if (url.startsWith(`${config.url}/static-assets`)) return url;
+ if (url.startsWith(`${config.url}/identicon`)) return url;
+ if (url.startsWith(`${config.url}/avatar`)) return url;
+
+ const meta = fetchMetaSync();
+ const baseUrl = meta ? meta.objectStorageBaseUrl ?? `${meta.objectStorageUseSSL ? "https" : "http"}://${meta.objectStorageEndpoint}${meta.objectStoragePort ? `:${meta.objectStoragePort}` : ""}/${meta.objectStorageBucket}` : null;
+ if (baseUrl !== null && url.startsWith(baseUrl)) return url;
+
+ return `${config.url}/proxy/${encodeURIComponent(new URL(url).pathname)}?${query({ url: url })}`;
+ },
+
+ getFinalUrlMaybe(url?: string | null): string | null {
+ if (url == null) return null;
+ return this.getFinalUrl(url);
+ },
+
async calcDriveUsageOf(
user: User["id"] | { id: User["id"] },
): Promise {
diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts
index 43523c95b..3a8b7874a 100644
--- a/packages/backend/src/models/repositories/user.ts
+++ b/packages/backend/src/models/repositories/user.ts
@@ -339,7 +339,7 @@ export const UserRepository = db.getRepository(User).extend({
this.getIdenticonUrl(user.id)
);
} else if (user.avatarId) {
- if (user.avatarUrl) return user.avatarUrl;
+ if (user.avatarUrl) return DriveFiles.getFinalUrl(user.avatarUrl);
const avatar = await DriveFiles.findOneByOrFail({ id: user.avatarId });
return (
DriveFiles.getPublicUrl(avatar, true) || this.getIdenticonUrl(user.id)
@@ -351,7 +351,7 @@ export const UserRepository = db.getRepository(User).extend({
getAvatarUrlSync(user: User): string {
if (user.avatarId && user.avatarUrl) {
- return user.avatarUrl;
+ return DriveFiles.getFinalUrl(user.avatarUrl);
} else if (user.avatar) {
return (
DriveFiles.getPublicUrl(user.avatar, true) ||
@@ -514,7 +514,7 @@ export const UserRepository = db.getRepository(User).extend({
lastFetchedAt: user.lastFetchedAt
? user.lastFetchedAt.toISOString()
: null,
- bannerUrl: user.bannerId ? (user.bannerUrl ?? (user.banner
+ bannerUrl: user.bannerId ? (DriveFiles.getFinalUrlMaybe(user.bannerUrl) ?? (user.banner
? DriveFiles.getPublicUrl(user.banner, false)
: null)) : null,
bannerBlurhash: user.bannerId ? (user.bannerBlurhash ?? user.banner?.blurhash ?? null) : null,
diff --git a/packages/backend/src/server/api/mastodon/converters/user.ts b/packages/backend/src/server/api/mastodon/converters/user.ts
index 07b9add43..5ac37e805 100644
--- a/packages/backend/src/server/api/mastodon/converters/user.ts
+++ b/packages/backend/src/server/api/mastodon/converters/user.ts
@@ -35,12 +35,14 @@ export class UserConverter {
const profile = UserProfiles.findOneBy({ userId: u.id });
const bio = profile.then(profile => MfmHelpers.toHtml(mfm.parse(profile?.description ?? ""), profile?.mentions, u.host).then(p => p ?? escapeMFM(profile?.description ?? "")));
const avatar = u.avatarId
- ? u.avatarUrl ?? (DriveFiles.findOneBy({ id: u.avatarId }))
+ ? DriveFiles.getFinalUrlMaybe(u.avatarUrl) ?? (DriveFiles.findOneBy({ id: u.avatarId }))
.then(p => p?.url ?? Users.getIdenticonUrl(u.id))
+ .then(p => DriveFiles.getFinalUrl(p))
: Users.getIdenticonUrl(u.id);
const banner = u.bannerId
- ? u.bannerUrl ?? (DriveFiles.findOneBy({ id: u.bannerId }))
- .then(p => p?.url ?? `${config.url}/static-assets/transparent.png`)
+ ? DriveFiles.getFinalUrlMaybe(u.bannerUrl) ?? (DriveFiles.findOneBy({ id: u.bannerId }))
+ .then(p => p?.url ?? `${config.url}/static-assets/transparent.png`)
+ .then(p => DriveFiles.getFinalUrl(p))
: `${config.url}/static-assets/transparent.png`;
const isFollowedOrSelf = !!localUser &&