Browse Source

请求头Range参数禁用

wuyi 2 tháng trước cách đây
mục cha
commit
a4b3dc11fa
1 tập tin đã thay đổi với 93 bổ sung0 xóa
  1. 93 0
      src/components/VideoJSPlayer.vue

+ 93 - 0
src/components/VideoJSPlayer.vue

@@ -92,6 +92,94 @@ 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 &&
+      typeof url === "string" &&
+      url.endsWith(".m3u8") &&
+      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 && url.endsWith(".m3u8")) {
+      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() !== ""
@@ -307,6 +395,9 @@ const initVideoJSPlayer = async (): Promise<void> => {
       poster: posterUrl, // 使用处理后的封面URL
     };
 
+    // 设置 XMLHttpRequest 拦截器以禁用 .m3u8 文件的 Range 请求
+    setupXHRInterceptor();
+
     try {
       // 注册快进按钮组件
       const registerSeekButtons = () => {
@@ -483,6 +574,8 @@ const destroyPlayer = (): void => {
     player.value.dispose();
     player.value = null;
   }
+  // 恢复 XMLHttpRequest 拦截器
+  restoreXHRInterceptor();
 };
 
 // 重试功能