async function handleRequest(request, env) { const { pathname, search } = new URL(request.url); // directly proxy the request if path matches official site's if (pathname === '/v1/chat/completions') return fetch(`https://api.openai.com/v1/chat/completions`, { method: request.method, headers: request.headers, body: request.body, }); const [_, token, action, user, ...params] = pathname.split('/'); if (!token || !action) throw 'Invalid request'; // register or refresh user's token if (action === 'register') { // validate against master token if (token !== env.ACCESS_TOKEN || !user) throw 'Access forbidden'; const text = await registerUser(user, env.OPENAI); return new Response(text, { headers: { 'Content-Type': 'text/plain' } }); } else if (action !== 'chat' || request.method !== 'POST') throw 'Invalid action'; // validate user const users = await env.OPENAI.get("users", {type: 'json'}) || {}; let name; for (let key in users) if (users[key].uuid === token) name = key; if (!name) throw 'Invalid token'; console.log(`User ${name} acepted.`); // proxy the request const url = new URL(request.url); // 1. force set API key and model const headers = new Headers(request.headers); headers.set('Authorization', `Bearer ${env.API_KEY}`); const payload = await request.json(); payload.model = 'gpt-3.5-turbo'; // 2. issue the underlying request return fetch(`https://api.openai.com/v1/chat/completions`, { method: request.method, headers: headers, body: JSON.stringify(payload), }); } async function registerUser(user, kv) { const users = await kv.get("users", {type: 'json'}) || {}; const uuid = generateUUID(); users[user] = {uuid}; await kv.put("users", JSON.stringify(users)); return uuid; } function generateUUID() { var d = new Date().getTime(); if (typeof performance !== 'undefined' && typeof performance.now === 'function'){ d += performance.now(); // use high-precision timer if available } var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = (d + Math.random()*16)%16 | 0; d = Math.floor(d/16); return (c=='x' ? r : (r&0x3|0x8)).toString(16); }); return uuid; } export default { async fetch(request, env) { return handleRequest(request, env).catch( err => new Response(err || 'Unknown reason', { status: 403 })) } };