File size: 3,568 Bytes
2889205
e4e9ad6
2889205
e4e9ad6
b0e1d6e
e4e9ad6
2889205
e4e9ad6
 
7f84064
2889205
7f84064
2889205
177a238
2889205
c4cb864
 
 
e5b45d3
 
 
 
 
 
 
 
 
 
e4e9ad6
 
 
 
dd4dc21
 
 
 
 
 
 
e4e9ad6
 
dd4dc21
 
 
 
 
 
 
 
 
 
 
 
e4e9ad6
dd4dc21
 
 
 
c4cb864
dd4dc21
 
 
 
c4cb864
dd4dc21
 
 
 
 
 
65e323a
dd4dc21
 
 
 
c4cb864
dd4dc21
 
 
c4cb864
 
 
 
e5b45d3
dd4dc21
65e323a
dd4dc21
 
 
 
65e323a
3e0d39c
177a238
dd4dc21
 
 
3e0d39c
 
e4e9ad6
 
 
 
177a238
65e323a
d5b575b
 
65e323a
315c31e
65e323a
2889205
 
e4e9ad6
dd4dc21
c4cb864
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
109
110
111
112
113
114
115
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 = {};

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();
}

app.use('/api/models/:model', authenticateApiKey, (req, res, next) => {
    const modelRequested = req.params.model;
    if (!allowedModels.includes(modelRequested)) {
        return res.status(403).send('The requested model is not permitted.');
    }
    next();
}, proxy(targetUrl, {
    proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
        proxyReqOpts.headers['Authorization'] = 'Bearer ' + openaiKey;
        return proxyReqOpts;
    }
}));

app.get("/", (req, res) => {
    let requestsInfo = requestDetails.map(detail =>
        `Request ${detail.requestNumber} on ${detail.timestamp} from API Key ${detail.apiKey}... with text "${detail.text}"`).join('<br>');
    res.send(`This is your OpenAI Reverse Proxy URL: ${baseUrl}.<br><br>Requests Overview:<br>${requestsInfo}`);
});

app.get('/logs', (req, res) => {
    res.sendFile(__dirname + '/index.html');
});

function getExternalUrl(spaceId) {
  try {
    const [username, spacename] = spaceId.split("/");
    return `https://${username}-${spacename.replace(/_/g, "-")}.hf.space/api/v1`;
  } catch (e) {
    return "Error generating external URL";
  }
}

server.listen(port, () => {
    const message = `Reverse proxy server and WebSocket running on port ${port}`;
    logAndEmit(message, true);
});