Files
Eduardo David Paredes Vara faaffc2a3b feat(memos): añadir proxy de reescritura de rutas para Authentik SSO
- proxy/server.js: proxy Node.js que reescribe la ruta del callback OAuth
  de Authentik (/auth/callback → /api/v1/auth/oauth/authentik/callback)
  resolviendo la incompatibilidad entre la URL que Authentik envía y la
  que espera Memos
- docker-compose.yml y stack.env: actualizados para incluir el proxy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 05:48:15 +00:00

82 lines
2.3 KiB
JavaScript

const http = require("http");
const { URL } = require("url");
const targetBase = process.env.MEMOS_UPSTREAM || "http://memos:5230";
const listenPort = Number(process.env.PORT || 8080);
function shouldRewrite(pathname) {
return /^\/api\/v1\/users\/[^/]+\/settings$/.test(pathname);
}
function filterSettingsPayload(buffer) {
const payload = JSON.parse(buffer.toString("utf8"));
if (!Array.isArray(payload.settings)) {
return buffer;
}
const settings = payload.settings.filter((item) => {
const name = String((item && item.name) || "");
return !name.endsWith("/unknown");
});
return Buffer.from(
JSON.stringify({
...payload,
settings,
totalSize: settings.length,
}),
"utf8",
);
}
const server = http.createServer((req, res) => {
const upstreamUrl = new URL(req.url, targetBase);
const headers = { ...req.headers };
headers.host = upstreamUrl.host;
const upstreamReq = http.request(
upstreamUrl,
{
method: req.method,
headers,
},
(upstreamRes) => {
const pathname = upstreamUrl.pathname;
const contentType = String(upstreamRes.headers["content-type"] || "");
const canRewrite = shouldRewrite(pathname) && contentType.includes("application/json");
if (!canRewrite) {
res.writeHead(upstreamRes.statusCode || 502, upstreamRes.headers);
upstreamRes.pipe(res);
return;
}
const chunks = [];
upstreamRes.on("data", (chunk) => chunks.push(chunk));
upstreamRes.on("end", () => {
try {
const body = filterSettingsPayload(Buffer.concat(chunks));
const responseHeaders = { ...upstreamRes.headers };
responseHeaders["content-length"] = String(body.length);
delete responseHeaders["content-encoding"];
res.writeHead(upstreamRes.statusCode || 200, responseHeaders);
res.end(body);
} catch (error) {
res.writeHead(502, { "content-type": "text/plain; charset=utf-8" });
res.end(`memos proxy rewrite failed: ${error.message}`);
}
});
},
);
upstreamReq.on("error", (error) => {
res.writeHead(502, { "content-type": "text/plain; charset=utf-8" });
res.end(`memos upstream error: ${error.message}`);
});
req.pipe(upstreamReq);
});
server.listen(listenPort, "0.0.0.0");