You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
2.4 KiB
84 lines
2.4 KiB
import { Fetcher, makeSimpleProxyFetcher } from "@movie-web/providers"; |
|
|
|
import { sendExtensionRequest } from "@/backend/extension/messaging"; |
|
import { getApiToken, setApiToken } from "@/backend/helpers/providerApi"; |
|
import { getProviderApiUrls, getProxyUrls } from "@/utils/proxyUrls"; |
|
|
|
function makeLoadbalancedList(getter: () => string[]) { |
|
let listIndex = -1; |
|
return () => { |
|
const fetchers = getter(); |
|
if (listIndex === -1 || listIndex >= fetchers.length) { |
|
listIndex = Math.floor(Math.random() * fetchers.length); |
|
} |
|
const proxyUrl = fetchers[listIndex]; |
|
listIndex = (listIndex + 1) % fetchers.length; |
|
return proxyUrl; |
|
}; |
|
} |
|
|
|
export const getLoadbalancedProxyUrl = makeLoadbalancedList(getProxyUrls); |
|
export const getLoadbalancedProviderApiUrl = |
|
makeLoadbalancedList(getProviderApiUrls); |
|
|
|
async function fetchButWithApiTokens( |
|
input: RequestInfo | URL, |
|
init?: RequestInit | undefined, |
|
): Promise<Response> { |
|
const apiToken = await getApiToken(); |
|
const headers = new Headers(init?.headers); |
|
if (apiToken) headers.set("X-Token", apiToken); |
|
const response = await fetch( |
|
input, |
|
init |
|
? { |
|
...init, |
|
headers, |
|
} |
|
: undefined, |
|
); |
|
const newApiToken = response.headers.get("X-Token"); |
|
if (newApiToken) setApiToken(newApiToken); |
|
return response; |
|
} |
|
|
|
export function makeLoadBalancedSimpleProxyFetcher() { |
|
const fetcher: Fetcher = async (a, b) => { |
|
const currentFetcher = makeSimpleProxyFetcher( |
|
getLoadbalancedProxyUrl(), |
|
fetchButWithApiTokens, |
|
); |
|
return currentFetcher(a, b); |
|
}; |
|
return fetcher; |
|
} |
|
|
|
function makeFinalHeaders( |
|
readHeaders: string[], |
|
headers: Record<string, string>, |
|
): Headers { |
|
const lowercasedHeaders = readHeaders.map((v) => v.toLowerCase()); |
|
return new Headers( |
|
Object.entries(headers).filter((entry) => |
|
lowercasedHeaders.includes(entry[0].toLowerCase()), |
|
), |
|
); |
|
} |
|
|
|
export function makeExtensionFetcher() { |
|
const fetcher: Fetcher = async (url, ops) => { |
|
const result = (await sendExtensionRequest<any>({ |
|
url, |
|
...ops, |
|
})) as any; |
|
if (!result?.success) throw new Error(`extension error: ${result?.error}`); |
|
const res = result.response; |
|
return { |
|
body: res.body, |
|
finalUrl: res.finalUrl, |
|
statusCode: res.statusCode, |
|
headers: makeFinalHeaders(ops.readHeaders, res.headers), |
|
}; |
|
}; |
|
return fetcher; |
|
}
|
|
|