|
import { Request, Response } from "express"; |
|
import * as http from "http"; |
|
import * as httpProxy from "http-proxy"; |
|
import { logger } from "../logger"; |
|
import { keys } from "../keys"; |
|
|
|
|
|
export const handleResponse = ( |
|
proxyRes: http.IncomingMessage, |
|
req: Request, |
|
res: Response |
|
) => { |
|
const statusCode = proxyRes.statusCode || 500; |
|
if (statusCode >= 400) { |
|
let body = ""; |
|
proxyRes.on("data", (chunk) => (body += chunk)); |
|
proxyRes.on("end", () => { |
|
let errorPayload: any = { |
|
error: "Proxy couldn't parse error from OpenAI", |
|
}; |
|
const canTryAgain = keys.anyAvailable() |
|
? "You can try again to get a different key." |
|
: "There are no more keys available."; |
|
try { |
|
errorPayload = JSON.parse(body); |
|
} catch (err) { |
|
logger.error({ error: err }, errorPayload.error); |
|
res.json(errorPayload); |
|
return; |
|
} |
|
|
|
if (statusCode === 401) { |
|
|
|
logger.warn( |
|
`OpenAI key is invalid or revoked. Keyhash ${req.key?.hash}` |
|
); |
|
keys.disable(req.key!); |
|
const message = `The OpenAI key is invalid or revoked. ${canTryAgain}`; |
|
errorPayload.proxy_note = message; |
|
} else if (statusCode === 429) { |
|
|
|
|
|
|
|
|
|
|
|
if (errorPayload.error?.type === "insufficient_quota") { |
|
logger.warn(`OpenAI key is exhausted. Keyhash ${req.key?.hash}`); |
|
keys.disable(req.key!); |
|
const message = `The OpenAI key is exhausted. ${canTryAgain}`; |
|
errorPayload.proxy_note = message; |
|
} else { |
|
logger.warn( |
|
{ errorCode: errorPayload.error?.type }, |
|
`OpenAI rate limit exceeded or model overloaded. Keyhash ${req.key?.hash}` |
|
); |
|
} |
|
} |
|
|
|
res.status(statusCode).json(errorPayload); |
|
}); |
|
} else { |
|
|
|
keys.incrementPrompt(req.key?.hash); |
|
|
|
Object.keys(proxyRes.headers).forEach((key) => { |
|
res.setHeader(key, proxyRes.headers[key] as string); |
|
}); |
|
proxyRes.pipe(res); |
|
} |
|
}; |
|
|
|
export const onError: httpProxy.ErrorCallback = (err, _req, res) => { |
|
logger.error({ error: err }, "Error proxying to OpenAI"); |
|
|
|
(res as http.ServerResponse).writeHead(500, { |
|
"Content-Type": "application/json", |
|
}); |
|
res.end( |
|
JSON.stringify({ |
|
error: { |
|
type: "proxy_error", |
|
message: err.message, |
|
proxy_note: |
|
"Reverse proxy encountered an error before it could reach OpenAI.", |
|
}, |
|
}) |
|
); |
|
}; |
|
|