mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-12 23:33:43 +08:00
fix: enforce compliance mode for managed deployments
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
export type DeploymentProvider = 'self-hosted' | 'vercel' | 'cloudflare';
|
||||
|
||||
export interface RuntimeFeatures {
|
||||
deploymentProvider: DeploymentProvider;
|
||||
deploymentProviderLabel: string;
|
||||
restrictedManagedDeployment: boolean;
|
||||
mediaProxyEnabled: boolean;
|
||||
iptvEnabled: boolean;
|
||||
restrictionSummary: string | null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import 'server-only';
|
||||
|
||||
import type { RuntimeFeatures } from '@/lib/config/runtime-features';
|
||||
|
||||
function isVercelDeployment(): boolean {
|
||||
return process.env.VERCEL === '1' || Boolean(process.env.VERCEL_ENV);
|
||||
}
|
||||
|
||||
function isCloudflareDeployment(): boolean {
|
||||
return (
|
||||
process.env.CF_PAGES === '1' ||
|
||||
Boolean(process.env.CF_PAGES_URL) ||
|
||||
Boolean(process.env.CLOUDFLARE_ACCOUNT_ID) ||
|
||||
Boolean(process.env.CF_ACCOUNT_ID) ||
|
||||
Boolean(process.env.WORKERS_CI)
|
||||
);
|
||||
}
|
||||
|
||||
function getRestrictedFeatures(
|
||||
deploymentProvider: RuntimeFeatures['deploymentProvider'],
|
||||
deploymentProviderLabel: string
|
||||
): RuntimeFeatures {
|
||||
return {
|
||||
deploymentProvider,
|
||||
deploymentProviderLabel,
|
||||
restrictedManagedDeployment: true,
|
||||
mediaProxyEnabled: false,
|
||||
iptvEnabled: false,
|
||||
restrictionSummary: `${deploymentProviderLabel} 托管部署会启用合规模式:关闭外部媒体代理、热链转发和 IPTV 流中继。需要这些能力时请改用 Docker 或传统 Node.js 自托管。`,
|
||||
};
|
||||
}
|
||||
|
||||
export function getRuntimeFeatures(): RuntimeFeatures {
|
||||
if (isVercelDeployment()) {
|
||||
return getRestrictedFeatures('vercel', 'Vercel');
|
||||
}
|
||||
|
||||
if (isCloudflareDeployment()) {
|
||||
return getRestrictedFeatures('cloudflare', 'Cloudflare');
|
||||
}
|
||||
|
||||
return {
|
||||
deploymentProvider: 'self-hosted',
|
||||
deploymentProviderLabel: '自托管',
|
||||
restrictedManagedDeployment: false,
|
||||
mediaProxyEnabled: true,
|
||||
iptvEnabled: true,
|
||||
restrictionSummary: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -103,17 +103,24 @@ export function parseSourcesFromJson(jsonString: string): ImportResult {
|
||||
* Fetch and parse sources from a URL
|
||||
*/
|
||||
export async function fetchSourcesFromUrl(url: string): Promise<ImportResult> {
|
||||
// If we're in the browser and it's an external URL, use our proxy to avoid CORS issues
|
||||
const headers = {
|
||||
'Accept': 'application/json',
|
||||
};
|
||||
const isExternal = url.startsWith('http') && (typeof window !== 'undefined' && !url.includes(window.location.host));
|
||||
const fetchUrl = isExternal
|
||||
? `/api/proxy?url=${encodeURIComponent(url)}`
|
||||
: url;
|
||||
|
||||
const response = await fetch(fetchUrl, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
});
|
||||
let response: Response;
|
||||
|
||||
try {
|
||||
response = await fetch(url, { headers });
|
||||
} catch (directError) {
|
||||
if (!isExternal) {
|
||||
throw directError;
|
||||
}
|
||||
|
||||
response = await fetch(`/api/proxy?url=${encodeURIComponent(url)}`, {
|
||||
headers,
|
||||
});
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`获取失败: ${response.status} ${response.statusText}`);
|
||||
|
||||
Reference in New Issue
Block a user