This gist is now deprecated and moved to janlay/openai-cloudflare. Stay tuned!
Last active
April 16, 2023 16:27
-
-
Save janlay/7cf20e24c7bffb0b56402eb9aa5e04cc to your computer and use it in GitHub Desktop.
OpenAPI Proxy for Cloudflare Workers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 })) | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment