faaffc2a3b
- 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>
82 lines
2.3 KiB
JavaScript
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");
|