Bladeren bron

Merge branch 'main' of https://git.izouma.com/wuyi/junma-show

wilhelm wong 2 maanden geleden
bovenliggende
commit
ee74feb842
2 gewijzigde bestanden met toevoegingen van 92 en 87 verwijderingen
  1. 2 87
      src/components/VideoJSPlayer.vue
  2. 90 0
      src/services/api.ts

+ 2 - 87
src/components/VideoJSPlayer.vue

@@ -92,89 +92,6 @@ const maxRetries = 3;
 const videoContainer = ref<HTMLDivElement>();
 const player = ref<any>(null);
 
-// 保存原始的 XMLHttpRequest.open 和 setRequestHeader 方法
-let originalXHROpen: any = null;
-let originalXHRSetRequestHeader: any = null;
-let originalFetch: any = null;
-let xhrInterceptorActive = false;
-
-// 设置 XMLHttpRequest 和 Fetch 拦截器以移除 Range 请求头
-const setupXHRInterceptor = (): void => {
-  if (xhrInterceptorActive) return;
-  
-  // 保存原始方法
-  originalXHROpen = XMLHttpRequest.prototype.open;
-  originalXHRSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
-  originalFetch = window.fetch;
-
-  // 拦截 XMLHttpRequest.open 方法
-  XMLHttpRequest.prototype.open = function (
-    method: string,
-    url: string | URL,
-    ...rest: any[]
-  ) {
-    // 保存 URL 以便后续检查
-    (this as any)._url = url.toString();
-    return originalXHROpen.apply(this, [method, url, ...rest]);
-  };
-
-  // 拦截 XMLHttpRequest.setRequestHeader 方法
-  XMLHttpRequest.prototype.setRequestHeader = function (
-    header: string,
-    value: string
-  ) {
-    // 如果是 .m3u8 文件的 Range 请求头,则跳过
-    const url = (this as any)._url || "";
-    if (url && /\.m3u8(\?|$)/i.test(url) && header.toLowerCase() === "range") {
-      return; // 不设置 Range 请求头
-    }
-    return originalXHRSetRequestHeader.apply(this, [header, value]);
-  };
-
-  // 拦截 fetch 方法
-  window.fetch = function (
-    input: RequestInfo | URL,
-    init?: RequestInit
-  ): Promise<Response> {
-    const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
-    
-    // 如果是 .m3u8 文件,移除 Range 请求头
-    if (url && /\.m3u8(\?|$)/i.test(url)) {
-      const modifiedInit = { ...init };
-      if (modifiedInit.headers) {
-        const headers = new Headers(modifiedInit.headers);
-        headers.delete("Range");
-        headers.delete("range");
-        modifiedInit.headers = headers;
-      } else {
-        modifiedInit.headers = new Headers();
-      }
-      return originalFetch.apply(this, [input, modifiedInit]);
-    }
-    
-    return originalFetch.apply(this, [input, init]);
-  };
-
-  xhrInterceptorActive = true;
-};
-
-// 恢复原始的 XMLHttpRequest 和 Fetch 方法
-const restoreXHRInterceptor = (): void => {
-  if (!xhrInterceptorActive) return;
-
-  if (originalXHROpen) {
-    XMLHttpRequest.prototype.open = originalXHROpen;
-  }
-  if (originalXHRSetRequestHeader) {
-    XMLHttpRequest.prototype.setRequestHeader = originalXHRSetRequestHeader;
-  }
-  if (originalFetch) {
-    window.fetch = originalFetch;
-  }
-
-  xhrInterceptorActive = false;
-};
-
 // 计算属性
 const hasVideoSource = computed(
   () => !!props.m3u8Url && props.m3u8Url.trim() !== ""
@@ -390,8 +307,7 @@ const initVideoJSPlayer = async (): Promise<void> => {
       poster: posterUrl, // 使用处理后的封面URL
     };
 
-    // 设置 XMLHttpRequest 拦截器以禁用 .m3u8 文件的 Range 请求
-    setupXHRInterceptor();
+    // 注意:拦截器已在 api.ts 中全局设置,无需在此处设置
 
     try {
       // 注册快进按钮组件
@@ -569,8 +485,7 @@ const destroyPlayer = (): void => {
     player.value.dispose();
     player.value = null;
   }
-  // 恢复 XMLHttpRequest 拦截器
-  restoreXHRInterceptor();
+  // 注意:拦截器在 api.ts 中全局管理,无需在此处恢复
 };
 
 // 重试功能

+ 90 - 0
src/services/api.ts

@@ -298,4 +298,94 @@ export const getVodList = async (
   return videoRequest(`/media/${plat_id}/menu/vods`, formData);
 };
 
+// ===================== 全局请求拦截器:移除 HLS 视频相关文件的 Range 请求头 =====================
+let originalXHROpen: any = null;
+let originalXHRSetRequestHeader: any = null;
+let originalFetch: any = null;
+let hlsInterceptorActive = false;
+
+const shouldRemoveRangeHeader = (url: string): boolean => {
+  if (!url) return false;
+
+  if (/\.m3u8(\?|$)/i.test(url)) {
+    return true;
+  }
+
+  if (
+    /\/dx\d+/i.test(url) || // 匹配 dx002, dx003 等
+    /\/[^\/]+\.ts(\?|$)/i.test(url) || // 匹配 .ts 分片文件
+    /\/segment\d+/i.test(url) || // 匹配 segment1, segment2 等
+    /\/chunk\d+/i.test(url)
+  ) {
+    return true;
+  }
+
+  return false;
+};
+
+/**
+ * 设置全局拦截器以移除 HLS 视频相关文件的 Range 请求头
+ */
+const setupHLSInterceptor = (): void => {
+  if (hlsInterceptorActive) return;
+
+  originalXHROpen = XMLHttpRequest.prototype.open;
+  originalXHRSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
+  originalFetch = window.fetch;
+
+  XMLHttpRequest.prototype.open = function (
+    method: string,
+    url: string | URL,
+    ...rest: any[]
+  ) {
+    (this as any)._url = url.toString();
+    return originalXHROpen.apply(this, [method, url, ...rest]);
+  };
+
+  XMLHttpRequest.prototype.setRequestHeader = function (
+    header: string,
+    value: string
+  ) {
+    const url = (this as any)._url || "";
+    if (shouldRemoveRangeHeader(url) && header.toLowerCase() === "range") {
+      return;
+    }
+    return originalXHRSetRequestHeader.apply(this, [header, value]);
+  };
+
+  window.fetch = function (
+    input: RequestInfo | URL,
+    init?: RequestInit
+  ): Promise<Response> {
+    const url =
+      typeof input === "string"
+        ? input
+        : input instanceof URL
+        ? input.toString()
+        : (input as Request).url;
+
+    if (shouldRemoveRangeHeader(url)) {
+      const modifiedInit = { ...init };
+      if (modifiedInit.headers) {
+        const headers = new Headers(modifiedInit.headers);
+        headers.delete("Range");
+        headers.delete("range");
+        modifiedInit.headers = headers;
+      } else {
+        modifiedInit.headers = new Headers();
+      }
+      return originalFetch.apply(this, [input, modifiedInit]);
+    }
+
+    return originalFetch.apply(this, [input, init]);
+  };
+
+  hlsInterceptorActive = true;
+  console.log("HLS Range Header Interceptor Activated");
+};
+
+if (typeof window !== "undefined") {
+  setupHLSInterceptor();
+}
+
 export default api;