Ayeantics commited on
Commit
dd4dc21
·
verified ·
1 Parent(s): c84c955

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +72 -33
server.js CHANGED
@@ -13,51 +13,89 @@ const openaiKey = process.env.OPENAI_KEY;
13
  const port = 7860;
14
  const baseUrl = getExternalUrl(process.env.SPACE_ID);
15
 
16
- let requestDetails = []; // Store details of each request
17
- let ipRequestCounts = {}; // Dictionary to keep track of requests per IP
18
 
19
  io.on('connection', (socket) => {
20
  console.log('A user connected to the websocket for live logs.');
21
  });
22
 
23
- function logAndEmit(message) {
24
- console.log(message); // Continue to log to the console
25
- io.emit('log', message); // Emit this log to the frontend via WebSocket
 
 
 
 
26
  }
27
 
28
- app.use('/api', (req, res, next) => {
29
- if (req.method === 'POST' && req.url.startsWith('/v1/chat/completions')) {
30
- const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
31
- ipRequestCounts[ip] = (ipRequestCounts[ip] || 0) + 1;
 
 
 
 
 
 
 
 
32
 
33
- const logMessage = `IP ${ip} has made ${ipRequestCounts[ip]} requests so far.`;
34
- logAndEmit(logMessage);
35
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
- const timestamp = moment().tz("Asia/Tbilisi").format("DD-MMM-YYYY HH:mm");
38
- const requestData = {
39
- requestNumber: ipRequestCounts[req.headers['x-forwarded-for'] || req.connection.remoteAddress],
40
- ip: req.headers['x-forwarded-for'] || req.connection.remoteAddress,
41
- timestamp: timestamp,
42
- text: req.method + ' ' + req.url
43
- };
44
- requestDetails.push(requestData);
45
-
46
- const detailedLog = `Request ${requestData.requestNumber} on ${requestData.timestamp} from IP ${requestData.ip} with method "${req.method}" and text "${requestData.text}"`;
47
- logAndEmit(detailedLog);
48
-
49
- next();
 
 
 
 
 
 
 
 
 
 
 
 
50
  }, proxy(targetUrl, {
51
- proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
52
- proxyReqOpts.headers['Authorization'] = 'Bearer ' + openaiKey;
53
- return proxyReqOpts;
54
- }
55
  }));
56
 
57
  app.get("/", (req, res) => {
58
- let requestsInfo = requestDetails.map(detail =>
59
- `Request ${detail.requestNumber} on ${detail.timestamp} from IP ${detail.ip} with text "${detail.text}"`).join('<br>');
60
- res.send(`This is your OpenAI Reverse Proxy URL: ${baseUrl}.<br><br>Requests Overview:<br>${requestsInfo}`);
61
  });
62
 
63
  app.get('/logs', (req, res) => {
@@ -74,5 +112,6 @@ function getExternalUrl(spaceId) {
74
  }
75
 
76
  server.listen(port, () => {
77
- logAndEmit(`Reverse proxy server and WebSocket running on port ${port}`);
 
78
  });
 
13
  const port = 7860;
14
  const baseUrl = getExternalUrl(process.env.SPACE_ID);
15
 
16
+ let requestDetails = [];
17
+ let apiKeyDetails = {}; // Track API key usage and first use timestamp
18
 
19
  io.on('connection', (socket) => {
20
  console.log('A user connected to the websocket for live logs.');
21
  });
22
 
23
+ function logAndEmit(message, includeTotal = false) {
24
+ if (includeTotal) {
25
+ const totalRequests = getTotalRequests();
26
+ message += ` Total requests so far: ${totalRequests}`;
27
+ }
28
+ console.log(message);
29
+ io.emit('log', message);
30
  }
31
 
32
+ function getTotalRequests() {
33
+ return Object.values(apiKeyDetails).reduce((acc, details) => acc + details.count, 0);
34
+ }
35
+
36
+ function authenticateApiKey(req, res, next) {
37
+ const receivedApiKey = req.headers['authorization'];
38
+ if (!receivedApiKey) {
39
+ return res.status(401).send('Unauthorized: No API key provided');
40
+ }
41
+
42
+ const validApiKeys = (process.env.SECRET_API_KEYS || '').split(',');
43
+ const apiKeyMatch = validApiKeys.find(key => `Bearer ${key.trim()}` === receivedApiKey);
44
 
45
+ if (!apiKeyMatch) {
46
+ return res.status(401).send('Unauthorized: API key is invalid');
47
+ }
48
+
49
+ const displayKey = apiKeyMatch.trim().substring(0, 7); // Only use the first four characters for display
50
+
51
+ if (!apiKeyDetails[apiKeyMatch]) {
52
+ apiKeyDetails[apiKeyMatch] = {
53
+ count: 0,
54
+ firstUse: moment() // Set the first use to now if it's not already set
55
+ };
56
+ }
57
+
58
+ // Check if more than a week has passed since the first use
59
+ if (moment().diff(apiKeyDetails[apiKeyMatch].firstUse, 'weeks') >= 1) {
60
+ return res.status(429).send(`API Key ${displayKey}... is blocked after one week of use.`);
61
+ }
62
 
63
+ // Increment the request count
64
+ apiKeyDetails[apiKeyMatch].count++;
65
+
66
+ const logMessage = `API Key ${displayKey}... used ${apiKeyDetails[apiKeyMatch].count} times so far.`;
67
+ logAndEmit(logMessage, true);
68
+
69
+ req.apiKey = apiKeyMatch; // Store the API key for the request
70
+ next();
71
+ }
72
+
73
+ app.use('/api', authenticateApiKey, (req, res, next) => {
74
+ const timestamp = moment().tz("Asia/Tbilisi").format("DD-MMM-YYYY HH:mm");
75
+ const displayKey = req.apiKey.substring(0, 4);
76
+ const requestData = {
77
+ requestNumber: apiKeyDetails[req.apiKey].count,
78
+ apiKey: displayKey,
79
+ timestamp: timestamp,
80
+ text: req.method + ' ' + req.url
81
+ };
82
+ requestDetails.push(requestData);
83
+
84
+ const detailedLog = `Request ${requestData.requestNumber} on ${requestData.timestamp} from API Key ${displayKey}... with method "${req.method}" and text "${requestData.text}"`;
85
+ logAndEmit(detailedLog, true);
86
+
87
+ next();
88
  }, proxy(targetUrl, {
89
+ proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
90
+ proxyReqOpts.headers['Authorization'] = 'Bearer ' + openaiKey;
91
+ return proxyReqOpts;
92
+ }
93
  }));
94
 
95
  app.get("/", (req, res) => {
96
+ let requestsInfo = requestDetails.map(detail =>
97
+ `Request ${detail.requestNumber} on ${detail.timestamp} from API Key ${detail.apiKey}... with text "${detail.text}"`).join('<br>');
98
+ res.send(`This is your OpenAI Reverse Proxy URL: ${baseUrl}.<br><br>Requests Overview:<br>${requestsInfo}`);
99
  });
100
 
101
  app.get('/logs', (req, res) => {
 
112
  }
113
 
114
  server.listen(port, () => {
115
+ const message = `Reverse proxy server and WebSocket running on port ${port}`;
116
+ logAndEmit(message, true); // true to include total requests in the log
117
  });