retrotoon-studio/server/_core/storageProxy.ts
Ubuntu c1606ad4c9 feat: migration complète Manus -> auto-hébergé (MinIO + Gemini)
Infrastructure:
- MinIO déployé en local pour le stockage S3 (docker-compose)
- Storage proxy réécrit: sert les fichiers depuis MinIO en streaming
  (plus de 307 redirect vers CDN externe)
- Legacy /manus-storage/ redirige vers /storage/

LLM & Image Generation:
- LLM: Gemini uniquement (suppression du fallback Forge)
- Image generation: Gemini Imagen direct (suppression Forge GenerateImage)
- llmConfig simplifié, un seul provider

Nettoyage Manus:
- Modules Forge stubbés (dataApi, heartbeat, map, notification, voiceTranscription)
- ENV simplifié (suppression forgeApiUrl, forgeApiKey)
- Analytics Manus supprimées du HTML
- systemRouter simplifié

Migration données:
- 750 fichiers migrés de Forge S3 vers MinIO (69.8 MB)
- URLs DB mises à jour: /manus-storage/ -> /storage/
- Script de migration inclus (scripts/migrate-to-minio.mjs)

Performance:
- Frame load: 500ms -> 62ms (8x plus rapide)
- Plus aucune dépendance réseau transatlantique pour le stockage

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-21 04:27:48 +00:00

38 lines
1.4 KiB
TypeScript

import type { Express } from "express";
export function registerStorageProxy(app: Express) {
const minioEndpoint = process.env.MINIO_ENDPOINT || "minio";
const minioPort = process.env.MINIO_PORT || "9000";
const bucket = process.env.MINIO_BUCKET || "retrotoon";
const minioBase = `http://${minioEndpoint}:${minioPort}/${bucket}`;
app.get("/storage/*", async (req, res) => {
const key = (req.params as Record<string, string>)[0];
if (!key) { res.status(400).send("Missing key"); return; }
try {
const upstream = await fetch(`${minioBase}/${key}`);
if (!upstream.ok) { res.status(upstream.status).send("Not found"); return; }
const contentType = upstream.headers.get("content-type") || "application/octet-stream";
const contentLength = upstream.headers.get("content-length");
res.set("Content-Type", contentType);
res.set("Cache-Control", "public, max-age=86400, immutable");
if (contentLength) res.set("Content-Length", contentLength);
const buffer = Buffer.from(await upstream.arrayBuffer());
res.send(buffer);
} catch (err) {
console.error("[StorageProxy] failed:", err);
res.status(502).send("Storage error");
}
});
// Legacy path
app.get("/manus-storage/*", (req, res) => {
const key = (req.params as Record<string, string>)[0];
if (!key) { res.status(400).send("Missing key"); return; }
res.redirect(301, `/storage/${key}`);
});
}