GeminiBot
commited on
Commit
·
4bca23b
1
Parent(s):
7bfd1f6
Port server from Bun to Node.js http module
Browse files- src/server.ts +81 -47
src/server.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
import { OpenAIService } from "./openai-service";
|
| 2 |
|
| 3 |
const openAIService = new OpenAIService();
|
|
@@ -33,54 +34,87 @@ const HTML_FRONTEND = `
|
|
| 33 |
</html>
|
| 34 |
`;
|
| 35 |
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
|
|
|
| 66 |
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
log(`REQ: ${lastMsg.substring(0, 50)}...`);
|
| 71 |
-
|
| 72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
return new Response(JSON.stringify({ error: error.message }), { status: 500, headers: corsHeaders });
|
| 79 |
-
}
|
| 80 |
-
},
|
| 81 |
-
});
|
| 82 |
-
|
| 83 |
-
log(`API Gateway started on port ${server.port}`);
|
| 84 |
-
} catch (error) {
|
| 85 |
-
process.exit(1);
|
| 86 |
-
}
|
|
|
|
| 1 |
+
import { createServer, IncomingMessage, ServerResponse } from "node:http";
|
| 2 |
import { OpenAIService } from "./openai-service";
|
| 3 |
|
| 4 |
const openAIService = new OpenAIService();
|
|
|
|
| 34 |
</html>
|
| 35 |
`;
|
| 36 |
|
| 37 |
+
const API_KEY = process.env.API_KEY || "MySecretKey_12345";
|
| 38 |
+
const PORT = Number(process.env.PORT) || 7860;
|
| 39 |
+
|
| 40 |
+
const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {
|
| 41 |
+
try {
|
| 42 |
+
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
| 43 |
+
const method = req.method;
|
| 44 |
+
|
| 45 |
+
// CORS Headers
|
| 46 |
+
const corsHeaders = {
|
| 47 |
+
"Access-Control-Allow-Origin": "*",
|
| 48 |
+
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
|
| 49 |
+
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
| 50 |
+
};
|
| 51 |
+
|
| 52 |
+
// Helper to send JSON response
|
| 53 |
+
const sendJSON = (statusCode: number, data: any) => {
|
| 54 |
+
res.writeHead(statusCode, { "Content-Type": "application/json", ...corsHeaders });
|
| 55 |
+
res.end(JSON.stringify(data));
|
| 56 |
+
};
|
| 57 |
+
|
| 58 |
+
// Helper to send HTML
|
| 59 |
+
const sendHTML = (html: string) => {
|
| 60 |
+
res.writeHead(200, { "Content-Type": "text/html", ...corsHeaders });
|
| 61 |
+
res.end(html);
|
| 62 |
+
};
|
| 63 |
+
|
| 64 |
+
// Masking Frontend
|
| 65 |
+
if (url.pathname === "/" && method === "GET") {
|
| 66 |
+
return sendHTML(HTML_FRONTEND);
|
| 67 |
+
}
|
| 68 |
|
| 69 |
+
// Handle Preflight
|
| 70 |
+
if (method === "OPTIONS") {
|
| 71 |
+
res.writeHead(204, corsHeaders);
|
| 72 |
+
res.end();
|
| 73 |
+
return;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
// Auth Check
|
| 77 |
+
const authHeader = req.headers["authorization"];
|
| 78 |
+
if (url.pathname.startsWith("/v1/") && authHeader !== `Bearer ${API_KEY}`) {
|
| 79 |
+
return sendJSON(401, { error: "Unauthorized" });
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
// Health Check
|
| 83 |
+
if (url.pathname === "/health") {
|
| 84 |
+
return sendJSON(200, { status: "online", model: "distributed-v1" });
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
// Chat Completions
|
| 88 |
+
if (url.pathname === "/v1/chat/completions" && method === "POST") {
|
| 89 |
+
let body = "";
|
| 90 |
+
req.on("data", (chunk) => { body += chunk; });
|
| 91 |
+
req.on("end", async () => {
|
| 92 |
+
try {
|
| 93 |
+
const jsonBody = JSON.parse(body);
|
| 94 |
+
const lastMsg = jsonBody.messages?.[jsonBody.messages.length - 1]?.content || "";
|
| 95 |
log(`REQ: ${lastMsg.substring(0, 50)}...`);
|
| 96 |
+
|
| 97 |
+
const completion = await openAIService.createChatCompletion(jsonBody);
|
| 98 |
+
sendJSON(200, completion);
|
| 99 |
+
} catch (error: any) {
|
| 100 |
+
log(`ERR: ${error.message}`);
|
| 101 |
+
sendJSON(500, { error: error.message });
|
| 102 |
}
|
| 103 |
+
});
|
| 104 |
+
return;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
// Not Found
|
| 108 |
+
res.writeHead(404, corsHeaders);
|
| 109 |
+
res.end();
|
| 110 |
+
|
| 111 |
+
} catch (error: any) {
|
| 112 |
+
log(`CRITICAL ERR: ${error.message}`);
|
| 113 |
+
res.writeHead(500, { "Content-Type": "application/json" });
|
| 114 |
+
res.end(JSON.stringify({ error: "Internal Server Error" }));
|
| 115 |
+
}
|
| 116 |
+
});
|
| 117 |
|
| 118 |
+
server.listen(PORT, () => {
|
| 119 |
+
log(`API Gateway started on port ${PORT}`);
|
| 120 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|