File size: 3,249 Bytes
2889205
e4e9ad6
2889205
e4e9ad6
b0e1d6e
e4e9ad6
2889205
e4e9ad6
 
7f84064
2889205
7f84064
2889205
177a238
2889205
c4cb864
cb7ac8f
c4cb864
cb7ac8f
e5b45d3
 
 
 
 
 
 
 
 
 
e4e9ad6
 
 
 
dd4dc21
 
 
 
 
 
 
e4e9ad6
 
dd4dc21
 
 
 
 
 
 
 
 
 
 
 
cb7ac8f
dd4dc21
 
 
 
c4cb864
dd4dc21
 
 
 
c4cb864
dd4dc21
 
 
 
 
 
65e323a
dd4dc21
cb7ac8f
dd4dc21
 
cb7ac8f
c4cb864
dd4dc21
 
 
cb7ac8f
 
 
 
 
 
e5b45d3
cb7ac8f
dd4dc21
cb7ac8f
 
 
 
 
 
dd4dc21
 
 
 
65e323a
3e0d39c
cb7ac8f
2889205
e4e9ad6
dd4dc21
cb7ac8f
3e0d39c
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
const express = require('express');
const http = require('http');
const proxy = require('express-http-proxy');
const socketIo = require('socket.io');
const moment = require('moment-timezone');

const app = express();
const server = http.createServer(app);
const io = socketIo(server);

const targetUrl = 'https://api.openai.com';
const openaiKey = process.env.OPENAI_KEY;
const port = 7860;
const baseUrl = getExternalUrl(process.env.SPACE_ID);

let requestDetails = [];
let apiKeyDetails = {}; // Track API key usage and first use timestamp

// Allowed models array
const allowedModels = [
    'gpt-3.5-turbo-0125',
    'gpt-3.5-turbo',
    'gpt-3.5-turbo-1106',
    'gpt-3.5-turbo-instruct',
    'gpt-3.5-turbo-16k',
    'gpt-3.5-turbo-0613',
    'gpt-3.5-turbo-16k-0613'
];

io.on('connection', (socket) => {
    console.log('A user connected to the websocket for live logs.');
});

function logAndEmit(message, includeTotal = false) {
    if (includeTotal) {
        const totalRequests = getTotalRequests();
        message += ` Total requests so far: ${totalRequests}`;
    }
    console.log(message);
    io.emit('log', message);
}

function getTotalRequests() {
    return Object.values(apiKeyDetails).reduce((acc, details) => acc + details.count, 0);
}

function authenticateApiKey(req, res, next) {
    const receivedApiKey = req.headers['authorization'];
    if (!receivedApiKey) {
        return res.status(401).send('Unauthorized: No API key provided');
    }

    const validApiKeys = (process.env.SECRET_API_KEYS || '').split(',');
    const apiKeyMatch = validApiKeys.find(key => `Bearer ${key.trim()}` === receivedApiKey);

    if (!apiKeyMatch) {
        return res.status(401).send('Unauthorized: API key is invalid');
    }

    const displayKey = apiKeyMatch.trim().substring(0, 7);

    if (!apiKeyDetails[apiKeyMatch]) {
        apiKeyDetails[apiKeyMatch] = {
            count: 0,
            firstUse: moment()
        };
    }

    if (moment().diff(apiKeyDetails[apiKeyMatch].firstUse, 'weeks') >= 1) {
        return res.status(429).send(`API Key ${displayKey}... is blocked after one week of use.`);
    }

    apiKeyDetails[apiKeyMatch].count++;

    const logMessage = `API Key ${displayKey}... used ${apiKeyDetails[apiKeyMatch].count} times so far.`;
    logAndEmit(logMessage, true);

    req.apiKey = apiKeyMatch;
    next();
}

function validateModel(req, res, next) {
    const pathComponents = req.path.split('/');
    const modelUsed = pathComponents.filter(component => allowedModels.includes(component))[0];

    if (!modelUsed) {
        return res.status(403).send("Access to this model is not allowed.");
    }

    next();
}

app.use('/api', authenticateApiKey, validateModel, proxy(targetUrl, {
    proxyReqPathResolver: function(req) {
        return require('url').parse(req.url).path;
    },
    proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
        proxyReqOpts.headers['Authorization'] = 'Bearer ' + openaiKey;
        return proxyReqOpts;
    }
}));

// Additional server endpoints remain unchanged

server.listen(port, () => {
    const message = `Reverse proxy server and WebSocket running on port ${port}`;
    logAndEmit(message, true); // true to include total requests in the log
});