feat: hacking FAL proxy to support 3rd party API
This commit is contained in:
parent
6be946325b
commit
4d3a325dee
33
apps/demo-nextjs-app-router/api_scripts/tuzi_api_test.sh
Normal file
33
apps/demo-nextjs-app-router/api_scripts/tuzi_api_test.sh
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# curl -v --location --request POST 'https://api.tu-zi.com/v1/chat/completions' \
|
||||||
|
# --header 'Content-Type: application/json' \
|
||||||
|
# --header 'Authorization: Bearer sk-...' \
|
||||||
|
# --data-raw '{
|
||||||
|
# "model": "gpt-4-gizmo-g-2fkFE8rbu",
|
||||||
|
# "messages": [
|
||||||
|
# {
|
||||||
|
# "role": "user",
|
||||||
|
# "content": "你是谁"
|
||||||
|
# }
|
||||||
|
# ],
|
||||||
|
# "stream": false
|
||||||
|
# }'
|
||||||
|
|
||||||
|
# echo
|
||||||
|
|
||||||
|
curl -v --location --request POST 'https://animator-gg-api.ca2324.servep2p.com:8443/api/fal/proxy' \
|
||||||
|
--header 'Content-Type: application/json' \
|
||||||
|
--header 'x-fal-target-url: https://api.tu-zi.com/v1/chat/completions' \
|
||||||
|
--data-raw '{
|
||||||
|
"model": "gpt-4-gizmo-g-2fkFE8rbu",
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "你是谁"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stream": false
|
||||||
|
}'
|
||||||
|
|
||||||
|
echo
|
||||||
@ -10,6 +10,9 @@ export type HeaderValue = string | string[] | undefined | null;
|
|||||||
|
|
||||||
const FAL_URL_REG_EXP = /(\.|^)fal\.(run|ai)$/;
|
const FAL_URL_REG_EXP = /(\.|^)fal\.(run|ai)$/;
|
||||||
|
|
||||||
|
const TUZI_API_KEY = process.env.TUZI_API_KEY;
|
||||||
|
const TUZI_URL_REG_EXP = /(\.|^)tu-zi\.com$/;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The proxy behavior that is passed to the proxy handler. This is a subset of
|
* The proxy behavior that is passed to the proxy handler. This is a subset of
|
||||||
* request objects that are used by different frameworks, like Express and NextJS.
|
* request objects that are used by different frameworks, like Express and NextJS.
|
||||||
@ -43,7 +46,6 @@ function singleHeaderValue(value: HeaderValue): string | undefined {
|
|||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFalKey(): string | undefined {
|
function getFalKey(): string | undefined {
|
||||||
if (FAL_KEY) {
|
if (FAL_KEY) {
|
||||||
return FAL_KEY;
|
return FAL_KEY;
|
||||||
@ -54,6 +56,18 @@ function getFalKey(): string | undefined {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getFalKeyForTargetHost(targetHost: string): string | undefined {
|
||||||
|
if (FAL_URL_REG_EXP.test(targetHost)) {
|
||||||
|
return getFalKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TUZI_URL_REG_EXP.test(targetHost)) {
|
||||||
|
return TUZI_API_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const EXCLUDED_HEADERS = ["content-length", "content-encoding"];
|
const EXCLUDED_HEADERS = ["content-length", "content-encoding"];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,14 +88,29 @@ export async function handleRequest<ResponseType>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const urlHost = new URL(targetUrl).host;
|
const urlHost = new URL(targetUrl).host;
|
||||||
if (!FAL_URL_REG_EXP.test(urlHost)) {
|
var targetApiKey = undefined;
|
||||||
return behavior.respondWith(412, `Invalid ${TARGET_URL_HEADER} header`);
|
var targetApiAuthHeader = undefined;
|
||||||
|
if (FAL_URL_REG_EXP.test(urlHost)) {
|
||||||
|
targetApiKey = getFalKey();
|
||||||
|
targetApiAuthHeader = `Key ${targetApiKey}`;
|
||||||
|
} else if (TUZI_URL_REG_EXP.test(urlHost)) {
|
||||||
|
targetApiKey = TUZI_API_KEY;
|
||||||
|
targetApiAuthHeader = `Bearer ${targetApiKey}`;
|
||||||
|
} else {
|
||||||
|
return behavior.respondWith(
|
||||||
|
412,
|
||||||
|
`Invalid ${TARGET_URL_HEADER} header with host: ${urlHost}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const falKey = behavior.resolveApiKey
|
// const falKey = behavior.resolveApiKey
|
||||||
? await behavior.resolveApiKey()
|
// ? await behavior.resolveApiKey()
|
||||||
: getFalKey();
|
// : getFalKeyForTargetHost(urlHost);
|
||||||
if (!falKey) {
|
// if (!falKey) {
|
||||||
|
// return behavior.respondWith(401, "Missing fal.ai credentials");
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (!targetApiKey) {
|
||||||
return behavior.respondWith(401, "Missing fal.ai credentials");
|
return behavior.respondWith(401, "Missing fal.ai credentials");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +130,7 @@ export async function handleRequest<ResponseType>(
|
|||||||
...headers,
|
...headers,
|
||||||
authorization:
|
authorization:
|
||||||
singleHeaderValue(behavior.getHeader("authorization")) ??
|
singleHeaderValue(behavior.getHeader("authorization")) ??
|
||||||
`Key ${falKey}`,
|
targetApiAuthHeader,
|
||||||
accept: "application/json",
|
accept: "application/json",
|
||||||
"content-type": "application/json",
|
"content-type": "application/json",
|
||||||
"user-agent": userAgent,
|
"user-agent": userAgent,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user