Skip to content

Instantly share code, notes, and snippets.

@janlay
Last active April 16, 2023 16:27
Show Gist options
  • Save janlay/7cf20e24c7bffb0b56402eb9aa5e04cc to your computer and use it in GitHub Desktop.
Save janlay/7cf20e24c7bffb0b56402eb9aa5e04cc to your computer and use it in GitHub Desktop.
OpenAPI Proxy for Cloudflare Workers
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