unknownfriend00007 commited on
Commit
403ad4e
·
verified ·
1 Parent(s): 3650c81

Create server.js

Browse files
Files changed (1) hide show
  1. server.js +135 -0
server.js ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const express = require('express');
2
+ const fetch = require('node-fetch');
3
+ const cors = require('cors');
4
+ const rateLimit = require('express-rate-limit');
5
+ require('dotenv').config();
6
+
7
+ const app = express();
8
+
9
+ // --- 1. SECURITY: TRUST PROXY ---
10
+ app.set('trust proxy', 1);
11
+
12
+ // --- 2. SECURITY: RATE LIMITING ---
13
+ const limiter = rateLimit({
14
+ windowMs: 15 * 60 * 1000,
15
+ max: 100,
16
+ standardHeaders: true,
17
+ legacyHeaders: false,
18
+ message: { error: "Too many requests, please try again later." }
19
+ });
20
+ app.use(limiter);
21
+
22
+ // --- 3. SECURITY: STRICT CORS ---
23
+ const allowedOrigins = process.env.ALLOWED_ORIGINS ? process.env.ALLOWED_ORIGINS.split(',') : [];
24
+
25
+ app.use(cors({
26
+ origin: function (origin, callback) {
27
+ if (!origin || allowedOrigins.length === 0) return callback(null, true);
28
+
29
+ if (allowedOrigins.indexOf(origin) !== -1) {
30
+ callback(null, true);
31
+ } else {
32
+ callback(new Error('Not allowed by CORS'));
33
+ }
34
+ }
35
+ }));
36
+
37
+ app.use(express.json());
38
+
39
+ // --- 4. MULTI-INSTANCE CONFIGURATION ---
40
+ let INSTANCES = [];
41
+ try {
42
+ INSTANCES = JSON.parse(process.env.FLOWISE_INSTANCES || '[]');
43
+ } catch (e) {
44
+ console.error("CRITICAL ERROR: Could not parse FLOWISE_INSTANCES JSON", e);
45
+ }
46
+
47
+ let flowDirectory = {};
48
+ let lastCacheUpdate = 0;
49
+
50
+ // --- 5. DYNAMIC DISCOVERY ---
51
+ async function refreshFlowDirectory() {
52
+ if (Date.now() - lastCacheUpdate < 60000 && Object.keys(flowDirectory).length > 0) return;
53
+
54
+ console.log(`[System] Scanning ${INSTANCES.length} Flowise Instances...`);
55
+ const newDirectory = {};
56
+
57
+ const promises = INSTANCES.map(async (inst) => {
58
+ try {
59
+ const headers = {};
60
+ if (inst.key && inst.key.length > 0) {
61
+ headers['Authorization'] = `Bearer ${inst.key}`;
62
+ }
63
+
64
+ const res = await fetch(`${inst.url}/api/v1/chatflows`, { headers });
65
+
66
+ if(!res.ok) throw new Error(`Status ${res.status}`);
67
+ const flows = await res.json();
68
+
69
+ flows.forEach(flow => {
70
+ const alias = flow.name.toLowerCase().replace(/\s+/g, '-');
71
+ newDirectory[alias] = {
72
+ id: flow.id,
73
+ host: inst.url,
74
+ key: inst.key
75
+ };
76
+ });
77
+ } catch (err) {
78
+ console.error(`[Error] Failed to fetch from ${inst.url}:`, err.message);
79
+ }
80
+ });
81
+
82
+ await Promise.allSettled(promises);
83
+
84
+ flowDirectory = newDirectory;
85
+ lastCacheUpdate = Date.now();
86
+ console.log(`[System] Directory Updated. Serving ${Object.keys(flowDirectory).length} bots.`);
87
+ }
88
+
89
+ // --- 6. THE ROUTE ---
90
+ app.post('/api/v1/prediction/:botName', async (req, res) => {
91
+ const botName = req.params.botName.toLowerCase();
92
+
93
+ await refreshFlowDirectory();
94
+
95
+ const target = flowDirectory[botName];
96
+
97
+ if (!target) {
98
+ lastCacheUpdate = 0;
99
+ await refreshFlowDirectory();
100
+ if (!flowDirectory[botName]) {
101
+ return res.status(404).json({ error: `Bot '${botName}' not found.` });
102
+ }
103
+ }
104
+
105
+ const finalTarget = flowDirectory[botName];
106
+
107
+ try {
108
+ const forwardHeaders = {
109
+ 'Content-Type': 'application/json',
110
+ 'HTTP-Referer': req.headers.origin || 'https://huggingface.co',
111
+ 'X-Title': 'FederatedProxy'
112
+ };
113
+
114
+ if (finalTarget.key && finalTarget.key.length > 0) {
115
+ forwardHeaders['Authorization'] = `Bearer ${finalTarget.key}`;
116
+ }
117
+
118
+ const flowiseResponse = await fetch(`${finalTarget.host}/api/v1/prediction/${finalTarget.id}`, {
119
+ method: 'POST',
120
+ headers: forwardHeaders,
121
+ body: JSON.stringify(req.body)
122
+ });
123
+
124
+ const data = await flowiseResponse.json();
125
+ res.status(flowiseResponse.status).json(data);
126
+
127
+ } catch (error) {
128
+ console.error("Proxy Forwarding Error:", error);
129
+ res.status(500).json({ error: 'Proxy forwarding failed.' });
130
+ }
131
+ });
132
+
133
+ app.get('/', (req, res) => res.send('Federated Proxy Active'));
134
+
135
+ app.listen(7860, '0.0.0.0', () => console.log('Federated Proxy running on port 7860'));