-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathapi.js
130 lines (106 loc) · 4.15 KB
/
api.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
const { getOllamaURL, sendWebhookNotification } = require('./utils');
const axios = require('axios');
const rateLimits = new Map();
function setupRoutes(app, db) {
app.use((req, res, next) => rateLimitMiddleware(req, res, next, db));
app.get('/health', (req, res) => healthCheck(req, res, db));
app.post('/generate', (req, res) => generateResponse(req, res, db));
}
function rateLimitMiddleware(req, res, next, db) {
const { apikey } = req.body;
if (!apikey) return next();
db.get('SELECT tokens, last_used, rate_limit, active FROM apiKeys WHERE key = ?', [apikey], (err, row) => {
if (err) {
console.error('Error checking API key for rate limit:', err.message);
return res.status(500).json({ error: 'Internal server error' });
}
if (row) {
if (row.active === 0) {
return res.status(403).json({ error: 'API key is deactivated' });
}
const currentTime = Date.now();
const minute = 60000;
const rateLimit = row.rate_limit;
if (!rateLimits.has(apikey)) {
rateLimits.set(apikey, { tokens: row.tokens, lastUsed: new Date(row.last_used).getTime() });
}
const rateLimitInfo = rateLimits.get(apikey);
const timeElapsed = currentTime - rateLimitInfo.lastUsed;
if (timeElapsed >= minute) {
rateLimitInfo.tokens = rateLimit;
}
if (rateLimitInfo.tokens > 0) {
rateLimitInfo.tokens -= 1;
rateLimitInfo.lastUsed = currentTime;
rateLimits.set(apikey, rateLimitInfo);
db.run('UPDATE apiKeys SET tokens = ?, last_used = ? WHERE key = ?', [rateLimitInfo.tokens, new Date(rateLimitInfo.lastUsed).toISOString(), apikey], (err) => {
if (err) {
console.error('Error updating tokens and last_used:', err.message);
return res.status(500).json({ error: 'Internal server error' });
}
next();
});
} else {
return res.status(429).json({ error: 'Rate limit exceeded. Try again later.' });
}
} else {
return res.status(403).json({ error: 'Invalid API key' });
}
});
}
function healthCheck(req, res, db) {
const apikey = req.query.apikey;
if (!apikey) {
return res.status(400).json({ error: 'API key is required' });
}
db.get('SELECT key FROM apiKeys WHERE key = ?', [apikey], (err, row) => {
if (err) {
console.error('Error checking API key:', err.message);
return res.status(500).json({ error: 'Internal server error' });
}
if (!row) {
console.log('Invalid API key:', apikey);
return res.status(403).json({ error: 'Invalid API Key' });
}
res.json({ status: 'API is healthy', timestamp: new Date() });
});
}
async function generateResponse(req, res, db) {
const { apikey, prompt, model, stream, images, raw } = req.body;
console.log('Request body:', req.body);
if (!apikey) {
return res.status(400).json({ error: 'API key is required' });
}
db.get('SELECT key FROM apiKeys WHERE key = ?', [apikey], async (err, row) => {
if (err) {
console.error('Error checking API key:', err.message);
return res.status(500).json({ error: 'Internal server error' });
}
if (!row) {
console.log('Invalid API key:', apikey);
return res.status(403).json({ error: 'Invalid API Key' });
}
try {
const ollamaURL = await getOllamaURL();
const OLLAMA_API_URL = `${ollamaURL}/api/generate`;
axios.post(OLLAMA_API_URL, { model, prompt, stream, images, raw })
.then(response => {
db.run('INSERT INTO apiUsage (key) VALUES (?)', [apikey], (err) => {
if (err) console.error('Error logging API usage:', err.message);
});
sendWebhookNotification(db, { apikey, prompt, model, stream, images, raw, timestamp: new Date() });
res.json(response.data);
})
.catch(error => {
console.error('Error making request to Ollama API:', error.message);
res.status(500).json({ error: 'Error making request to Ollama API' });
});
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Error retrieving Ollama server port' });
}
});
}
module.exports = {
setupRoutes
};