Spaces:
Paused
Paused
| const express = require('express'); | |
| const { createProxyMiddleware, fixRequestBody } = require('http-proxy-middleware'); | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const app = express(); | |
| const proxyCache = {}; | |
| // 1. GLOBAL CORS INTERCEPTOR | |
| // This stops SillyTavern/JanitorAI preflight requests from reaching NIM and getting rejected. | |
| app.use((req, res, next) => { | |
| res.setHeader('Access-Control-Allow-Origin', '*'); | |
| res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); | |
| res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); | |
| if (req.method === 'OPTIONS') { | |
| return res.sendStatus(200); // Instantly approve all preflights | |
| } | |
| next(); | |
| }); | |
| // Parse incoming bodies (required to inject NIM's thinking parameters) | |
| app.use(express.json({ limit: '50mb' })); | |
| // Load Endpoints | |
| let endpoints = {}; | |
| try { | |
| endpoints = JSON.parse(fs.readFileSync(path.join(__dirname, 'endpoints.json'), 'utf8')); | |
| console.log("β Loaded Endpoints:", Object.keys(endpoints).join(', ')); | |
| } catch (e) { | |
| console.error("β Error: endpoints.json missing or invalid."); | |
| } | |
| app.use(express.static(path.join(__dirname, 'public'))); | |
| app.get('/api/endpoints', (req, res) => res.json(endpoints)); | |
| // 2. THE SMART PROXY | |
| app.use('/:nick', (req, res, next) => { | |
| const { nick } = req.params; | |
| // Ignore internal or invalid routes | |
| if (nick === 'api' || !endpoints[nick]) return next(); | |
| if (!proxyCache[nick]) { | |
| const target = endpoints[nick].url; | |
| console.log(`[Setup] Routing /${nick} -> ${target}`); | |
| // Logic to inject GLM 5.1 Thinking Parameters | |
| const handleProxyReq = (proxyReq, req, res) => { | |
| if (req.method === 'POST' && req.body) { | |
| if (nick === 'nim') { | |
| req.body.chat_template_kwargs = { | |
| enable_thinking: true, | |
| clear_thinking: false | |
| }; | |
| // Map unsupported roles | |
| if (req.body.messages && Array.isArray(req.body.messages)) { | |
| req.body.messages.forEach(msg => { | |
| if (msg.role === 'developer') msg.role = 'system'; | |
| }); | |
| } | |
| } | |
| // Safely repackage the modified JSON body | |
| fixRequestBody(proxyReq, req); | |
| } | |
| }; | |
| const handleError = (err, req, res) => { | |
| console.error(`[Error: ${nick}]`, err.message); | |
| if (!res.headersSent) { | |
| res.status(502).json({ error: "Provider Offline or Connection Timeout." }); | |
| } | |
| }; | |
| proxyCache[nick] = createProxyMiddleware({ | |
| target: target, | |
| changeOrigin: true, | |
| pathRewrite: { [`^/${nick}`]: '' }, | |
| // 3. DUAL-COMPATIBILITY HOOKS | |
| // Guarantees fixRequestBody fires regardless of the middleware version installed | |
| // --- Legacy v2 Syntax --- | |
| onProxyReq: handleProxyReq, | |
| onError: handleError, | |
| // --- Modern v3 Syntax --- | |
| on: { | |
| proxyReq: handleProxyReq, | |
| error: handleError | |
| } | |
| }); | |
| } | |
| return proxyCache[nick](req, res, next); | |
| }); | |
| const PORT = 7860; | |
| app.listen(PORT, '0.0.0.0', () => console.log(`π Hub active on port ${PORT}`)); |