Hamed744 commited on
Commit
c580b6f
·
verified ·
1 Parent(s): a2bb79a

Update server/Server.js

Browse files
Files changed (1) hide show
  1. server/Server.js +23 -44
server/Server.js CHANGED
@@ -2,59 +2,47 @@ const express = require('express');
2
  const path = require('node:path');
3
  const { WebSocketServer, WebSocket } = require('ws');
4
  const http = require('node:http');
5
- require('dotenv').config(); // برای خواندن GEMINI_API_KEY از .env
6
 
7
  const app = express();
8
  const server = http.createServer(app);
9
 
10
- // --- 👇 دامنه مجاز WebSocket (باید با ALLOWED_ORIGIN در App.tsx یکی باشد) 👇 ---
11
  const ALLOWED_WEBSOCKET_ORIGIN = "https://aisada.ir"; // یا "http://aisada.ir"
12
- // --- 👆 ---
13
 
14
- // --- 👇 استفاده از verifyClient برای بررسی Origin قبل از نهایی کردن اتصال 👇 ---
15
  const wss = new WebSocketServer({
16
- server, // سرور HTTP که به آن متصل می‌شود
17
  verifyClient: (info, cb) => {
18
- // info.origin حاوی مقدار هدر Origin فرستاده شده توسط مرورگر است
19
  const origin = info.origin;
20
- console.log(`[WebSocket Verify] Verifying origin: ${origin}`); // لاگ برای دیباگ
21
-
22
  if (origin === ALLOWED_WEBSOCKET_ORIGIN) {
23
  console.log(`[WebSocket Verify] Origin allowed: ${origin}`);
24
- cb(true); // اتصال مجاز است، ادامه بده
25
  } else {
26
- // اگر origin تعریف نشده بود (مثلاً یک کلاینت غیرمرورگری) یا مطابقت نداشت
27
  console.warn(`[WebSocket Verify] Forbidden origin: ${origin}. Rejecting connection.`);
28
- // cb(accept, code, message)
29
- cb(false, 403, 'Forbidden Origin'); // اتصال را با کد 403 رد کن
30
  }
31
  }
32
  });
33
- // --- 👆 ---
34
 
35
- // Serve static files from the React app build directory
36
- // این مسیر باید درست باشد نسبت به محل اجرای server.js
37
  app.use(express.static(path.join(__dirname, '../build')));
38
 
39
- // خواندن API Key از متغیرهای محیطی
40
  const GEMINI_API_KEY = process.env.GEMINI_API_KEY;
41
-
42
  if (!GEMINI_API_KEY) {
43
  console.error('FATAL ERROR: GEMINI_API_KEY environment variable is not set!');
44
- process.exit(1); // خروج از برنامه اگر کلید وجود ندارد
45
  }
46
 
47
- // تابع برای ایجاد اتصال WebSocket به Gemini (بدون تغییر نسبت به قبل)
48
  const createGeminiWebSocket = (clientWs) => {
49
- const geminiWsUrl = `wss://generativelanguage.googleapis.com/v1beta/models/gemini-pro:streamGenerateContent?key=${GEMINI_API_KEY}&alt=sse`; // URL ممکن است نیاز به آپدیت داشته باشد
50
- // یا URL قبلی: `wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1alpha.GenerativeService.BidiGenerateContent?key=${GEMINI_API_KEY}`
51
- console.log(`[Gemini Connect] Attempting connection to Gemini: ${geminiWsUrl.split('key=')[0]}...`); // عدم لاگ کلید
52
- const geminiWs = new WebSocket(geminiWsUrl); // از URL صحیح استفاده کنید
53
 
54
  geminiWs.on('open', () => {
55
  console.log('[Gemini Connect] Connected to Gemini API');
56
  if (geminiWs.pendingSetup) {
57
- console.log('[Gemini Connect] Sending pending setup:', geminiWs.pendingSetup);
 
58
  geminiWs.send(JSON.stringify(geminiWs.pendingSetup));
59
  geminiWs.pendingSetup = null;
60
  }
@@ -62,14 +50,12 @@ const createGeminiWebSocket = (clientWs) => {
62
 
63
  geminiWs.on('message', (data) => {
64
  try {
65
- console.log('[Gemini Receive] Received from Gemini'); // حذف لاگ کامل محتوا برای امنیت/حجم
66
- // ارسال پیام به کلاینت اصلی
67
  if (clientWs.readyState === WebSocket.OPEN) {
68
- // اگر بافر بود، مستقیم بفرست
69
  if (Buffer.isBuffer(data)) {
70
  clientWs.send(data, { binary: true });
71
  } else {
72
- // اگر متن بود، تبدیل به بافر و ارسال (مطابق کد قبلی)
73
  const blob = Buffer.from(data.toString());
74
  clientWs.send(blob, { binary: true });
75
  }
@@ -85,9 +71,7 @@ const createGeminiWebSocket = (clientWs) => {
85
  return geminiWs;
86
  };
87
 
88
- // رویداد connection حالا فقط برای درخواست‌های مجاز اجرا می‌شود
89
  wss.on('connection', (ws, req) => {
90
- // req.headers.origin را برای لاگ استفاده می‌کنیم
91
  const origin = req.headers.origin || 'N/A';
92
  console.log(`[WebSocket Event] Client connected (Origin: ${origin})`);
93
  let geminiWs = null;
@@ -96,12 +80,13 @@ wss.on('connection', (ws, req) => {
96
  try {
97
  const messageString = message.toString();
98
  const data = JSON.parse(messageString);
99
- console.log('[Client Receive] Received from client'); // حذف لاگ کامل محتوا
 
100
 
101
  if (data.setup) {
 
102
  console.log('[Client Receive] Initializing Gemini connection...');
103
  geminiWs = createGeminiWebSocket(ws);
104
- // مدیریت پیام setup که قبل از باز شدن اتصال gemini می‌رسد
105
  if (geminiWs.readyState !== WebSocket.OPEN) {
106
  geminiWs.pendingSetup = data;
107
  } else {
@@ -110,19 +95,17 @@ wss.on('connection', (ws, req) => {
110
  return;
111
  }
112
 
113
- // ارسال سایر پیام‌ها به Gemini
114
  if (geminiWs && geminiWs.readyState === WebSocket.OPEN) {
115
  geminiWs.send(JSON.stringify(data));
116
  } else if (geminiWs) {
 
117
  console.log('[Client Receive] Gemini connection not ready, waiting...');
118
- // اینجا می‌توان پیام را در صف گذاشت یا خطا داد
119
  } else {
120
  console.error('[Client Receive] No Gemini connection established. Closing client connection.');
121
- ws.close(1011, 'Backend connection not ready'); // بستن اتصال کلاینت
122
  }
123
  } catch (error) {
124
- console.error('[Client Receive] Error processing message:', error, message.toString().substring(0, 100) + '...'); // لاگ خلاصه پیام خطا
125
- // بستن اتصال در صورت خطای parse یا پردازش ناموفق
126
  ws.close(1008, 'Message processing error');
127
  }
128
  });
@@ -133,18 +116,16 @@ wss.on('connection', (ws, req) => {
133
  console.log('[WebSocket Event] Closing associated Gemini connection.');
134
  geminiWs.close();
135
  }
136
- geminiWs = null; // پاک کردن رفرنس
137
  });
138
 
139
  ws.on('error', (error) => {
140
  console.error('[WebSocket Event] Client WebSocket error:', error);
141
- // بستن اتصال جمینی در صورت خطای کلاینت
142
  if (geminiWs && geminiWs.readyState !== WebSocket.CLOSED && geminiWs.readyState !== WebSocket.CLOSING) {
143
  console.log('[WebSocket Event] Closing associated Gemini connection due to client error.');
144
  geminiWs.close();
145
  }
146
  geminiWs = null;
147
- // خود ws معمولا به طور خودکار بسته می‌شود، اما برای اطمینان:
148
  if (ws.readyState !== WebSocket.CLOSED && ws.readyState !== WebSocket.CLOSING) {
149
  ws.close(1011, 'Client error');
150
  }
@@ -152,14 +133,12 @@ wss.on('connection', (ws, req) => {
152
 
153
  });
154
 
155
- // سرو کردن فایل‌های استاتیک React (مسیر build)
156
  app.get('*', (req, res) => {
157
- res.sendFile(path.resolve(__dirname, '../build', 'index.html')); // استفاده از path.resolve برای اطمینان
158
  });
159
 
160
- // اجرای سرور
161
  const PORT = process.env.PORT || 3001;
162
  server.listen(PORT, () => {
163
  console.log(`Server listening on port ${PORT}`);
164
- console.log(`Allowed WebSocket Origin: ${ALLOWED_WEBSOCKET_ORIGIN}`); // نمایش دامنه مجاز در لاگ
165
  });
 
2
  const path = require('node:path');
3
  const { WebSocketServer, WebSocket } = require('ws');
4
  const http = require('node:http');
5
+ require('dotenv').config();
6
 
7
  const app = express();
8
  const server = http.createServer(app);
9
 
 
10
  const ALLOWED_WEBSOCKET_ORIGIN = "https://aisada.ir"; // یا "http://aisada.ir"
 
11
 
 
12
  const wss = new WebSocketServer({
13
+ server,
14
  verifyClient: (info, cb) => {
 
15
  const origin = info.origin;
16
+ // --- 👇 لاگ Verify را نگه می‌داریم چون مهم است 👇 ---
17
+ console.log(`[WebSocket Verify] Verifying origin: ${origin}`);
18
  if (origin === ALLOWED_WEBSOCKET_ORIGIN) {
19
  console.log(`[WebSocket Verify] Origin allowed: ${origin}`);
20
+ cb(true);
21
  } else {
 
22
  console.warn(`[WebSocket Verify] Forbidden origin: ${origin}. Rejecting connection.`);
23
+ cb(false, 403, 'Forbidden Origin');
 
24
  }
25
  }
26
  });
 
27
 
 
 
28
  app.use(express.static(path.join(__dirname, '../build')));
29
 
 
30
  const GEMINI_API_KEY = process.env.GEMINI_API_KEY;
 
31
  if (!GEMINI_API_KEY) {
32
  console.error('FATAL ERROR: GEMINI_API_KEY environment variable is not set!');
33
+ process.exit(1);
34
  }
35
 
 
36
  const createGeminiWebSocket = (clientWs) => {
37
+ const geminiWsUrl = `wss://generativelanguage.googleapis.com/v1beta/models/gemini-pro:streamGenerateContent?key=${GEMINI_API_KEY}&alt=sse`;
38
+ console.log(`[Gemini Connect] Attempting connection to Gemini...`);
39
+ const geminiWs = new WebSocket(geminiWsUrl);
 
40
 
41
  geminiWs.on('open', () => {
42
  console.log('[Gemini Connect] Connected to Gemini API');
43
  if (geminiWs.pendingSetup) {
44
+ // لاگ pendingSetup ممکن است حجیم باشد، خلاصه‌تر می‌کنیم
45
+ console.log('[Gemini Connect] Sending pending setup...');
46
  geminiWs.send(JSON.stringify(geminiWs.pendingSetup));
47
  geminiWs.pendingSetup = null;
48
  }
 
50
 
51
  geminiWs.on('message', (data) => {
52
  try {
53
+ // --- 👇 لاگ دریافت از Gemini حذف شد 👇 ---
54
+ // console.log('[Gemini Receive] Received from Gemini');
55
  if (clientWs.readyState === WebSocket.OPEN) {
 
56
  if (Buffer.isBuffer(data)) {
57
  clientWs.send(data, { binary: true });
58
  } else {
 
59
  const blob = Buffer.from(data.toString());
60
  clientWs.send(blob, { binary: true });
61
  }
 
71
  return geminiWs;
72
  };
73
 
 
74
  wss.on('connection', (ws, req) => {
 
75
  const origin = req.headers.origin || 'N/A';
76
  console.log(`[WebSocket Event] Client connected (Origin: ${origin})`);
77
  let geminiWs = null;
 
80
  try {
81
  const messageString = message.toString();
82
  const data = JSON.parse(messageString);
83
+ // --- 👇 لاگ دریافت از Client حذف شد 👇 ---
84
+ // console.log('[Client Receive] Received from client');
85
 
86
  if (data.setup) {
87
+ // لاگ setup را نگه می‌داریم چون مهم است
88
  console.log('[Client Receive] Initializing Gemini connection...');
89
  geminiWs = createGeminiWebSocket(ws);
 
90
  if (geminiWs.readyState !== WebSocket.OPEN) {
91
  geminiWs.pendingSetup = data;
92
  } else {
 
95
  return;
96
  }
97
 
 
98
  if (geminiWs && geminiWs.readyState === WebSocket.OPEN) {
99
  geminiWs.send(JSON.stringify(data));
100
  } else if (geminiWs) {
101
+ // لاگ انتظار را نگه می‌داریم
102
  console.log('[Client Receive] Gemini connection not ready, waiting...');
 
103
  } else {
104
  console.error('[Client Receive] No Gemini connection established. Closing client connection.');
105
+ ws.close(1011, 'Backend connection not ready');
106
  }
107
  } catch (error) {
108
+ console.error('[Client Receive] Error processing message:', error, message.toString().substring(0, 100) + '...');
 
109
  ws.close(1008, 'Message processing error');
110
  }
111
  });
 
116
  console.log('[WebSocket Event] Closing associated Gemini connection.');
117
  geminiWs.close();
118
  }
119
+ geminiWs = null;
120
  });
121
 
122
  ws.on('error', (error) => {
123
  console.error('[WebSocket Event] Client WebSocket error:', error);
 
124
  if (geminiWs && geminiWs.readyState !== WebSocket.CLOSED && geminiWs.readyState !== WebSocket.CLOSING) {
125
  console.log('[WebSocket Event] Closing associated Gemini connection due to client error.');
126
  geminiWs.close();
127
  }
128
  geminiWs = null;
 
129
  if (ws.readyState !== WebSocket.CLOSED && ws.readyState !== WebSocket.CLOSING) {
130
  ws.close(1011, 'Client error');
131
  }
 
133
 
134
  });
135
 
 
136
  app.get('*', (req, res) => {
137
+ res.sendFile(path.resolve(__dirname, '../build', 'index.html'));
138
  });
139
 
 
140
  const PORT = process.env.PORT || 3001;
141
  server.listen(PORT, () => {
142
  console.log(`Server listening on port ${PORT}`);
143
+ console.log(`Allowed WebSocket Origin: ${ALLOWED_WEBSOCKET_ORIGIN}`);
144
  });