103 lines
3.7 KiB
TypeScript
103 lines
3.7 KiB
TypeScript
import { Express, Request, Response } from "express";
|
|
import { createProxyMiddleware } from "http-proxy-middleware";
|
|
import { startLaravelServer } from "./launcher";
|
|
|
|
const PLUS_HOST = process.env.PLUS_HOST || "localhost";
|
|
const PLUS_PORT = parseInt(process.env.PLUS_PORT || "8080", 10);
|
|
const PLUS_TIMEOUT = parseInt(process.env.PLUS_TIMEOUT || "60000", 10);
|
|
const AUTO_START = process.env.PLUS_AUTO_START !== "false";
|
|
|
|
export async function setupPlusProxy(app: Express): Promise<void> {
|
|
const plusTarget = `http://${PLUS_HOST}:${PLUS_PORT}`;
|
|
|
|
if (AUTO_START) {
|
|
await startLaravelServer();
|
|
}
|
|
|
|
// Simple transparent proxy - only rewrite Location headers
|
|
const plusProxy = createProxyMiddleware({
|
|
target: plusTarget,
|
|
changeOrigin: true,
|
|
timeout: PLUS_TIMEOUT,
|
|
proxyTimeout: PLUS_TIMEOUT,
|
|
pathRewrite: {
|
|
"^/plus": "",
|
|
},
|
|
on: {
|
|
error: (err, req, res) => {
|
|
console.error("[Plus Proxy] Error:", err.message);
|
|
if (res && typeof (res as Response).status === "function") {
|
|
(res as Response).status(502).json({
|
|
error: "Arcádia Plus não disponível",
|
|
message: `Laravel não está rodando em ${plusTarget}`
|
|
});
|
|
}
|
|
},
|
|
proxyReq: (proxyReq, req) => {
|
|
console.log(`[Plus Proxy] ${req.method} ${req.url} -> ${plusTarget}`);
|
|
// Forward host and protocol headers for Laravel URL generation
|
|
const forwardedHost = req.headers['x-forwarded-host'];
|
|
const host = (typeof forwardedHost === 'string' ? forwardedHost : req.headers.host) || 'localhost';
|
|
const forwardedProto = req.headers['x-forwarded-proto'];
|
|
const proto = (typeof forwardedProto === 'string' ? forwardedProto : 'https');
|
|
proxyReq.setHeader('X-Forwarded-Host', host);
|
|
proxyReq.setHeader('X-Forwarded-Proto', proto);
|
|
proxyReq.setHeader('X-Forwarded-Prefix', '/plus');
|
|
},
|
|
proxyRes: (proxyRes) => {
|
|
const location = proxyRes.headers["location"];
|
|
if (location && typeof location === "string") {
|
|
let newLocation = location;
|
|
// Rewrite localhost:8080 URLs to /plus
|
|
newLocation = newLocation.replace(`http://${PLUS_HOST}:${PLUS_PORT}`, "/plus");
|
|
newLocation = newLocation.replace(/http:\/\/localhost:8080/g, "/plus");
|
|
// If it's a relative path, add /plus prefix
|
|
if (newLocation.startsWith("/") && !newLocation.startsWith("/plus")) {
|
|
newLocation = "/plus" + newLocation;
|
|
}
|
|
proxyRes.headers["location"] = newLocation;
|
|
}
|
|
},
|
|
},
|
|
});
|
|
|
|
// All Plus routes go through simple proxy (including auto-login)
|
|
// Laravel handles its own authentication via /plus/auto-login
|
|
app.use("/plus", plusProxy);
|
|
|
|
// Status check
|
|
app.get("/api/plus/status", async (_req: Request, res: Response) => {
|
|
try {
|
|
const controller = new AbortController();
|
|
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
|
|
const response = await fetch(`${plusTarget}/api/health`, {
|
|
signal: controller.signal
|
|
});
|
|
clearTimeout(timeout);
|
|
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
res.json({
|
|
status: "online",
|
|
host: PLUS_HOST,
|
|
port: PLUS_PORT,
|
|
app: data.app,
|
|
version: data.version
|
|
});
|
|
} else {
|
|
res.json({ status: "error", host: PLUS_HOST, port: PLUS_PORT, httpStatus: response.status });
|
|
}
|
|
} catch (err: any) {
|
|
res.json({
|
|
status: "offline",
|
|
host: PLUS_HOST,
|
|
port: PLUS_PORT,
|
|
error: err.name === 'AbortError' ? 'timeout' : err.message
|
|
});
|
|
}
|
|
});
|
|
|
|
console.log(`[Plus Proxy] Configurado: /plus -> ${plusTarget}`);
|
|
}
|