@skrillex1224/playwright-toolkit 2.1.136 → 2.1.137

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1852,7 +1852,6 @@ var Interception = {
1852
1852
  * @param {Object} [options] - 配置选项
1853
1853
  * @param {string[]} [options.directDomains] - [已过时] 需要直连的域名列表,请改用 directConfig.domains
1854
1854
  * @param {Object} [options.directConfig] - 直连配置(参考 blockingConfig),支持 domains/directAllXxx 系列开关
1855
- * @param {boolean|Function} [options.enable] - 是否启用拦截处理(false 时始终 continue)
1856
1855
  * @param {Object} [options.blockingConfig] - 资源屏蔽配置
1857
1856
  * @param {boolean} [options.fallbackToProxy] - 直连失败时是否回退到代理(默认 true)
1858
1857
  * @returns {Promise<void>}
@@ -1861,7 +1860,6 @@ var Interception = {
1861
1860
  const {
1862
1861
  directDomains = [],
1863
1862
  directConfig = {},
1864
- enable = true,
1865
1863
  blockingConfig = {},
1866
1864
  fallbackToProxy = true
1867
1865
  } = options;
@@ -1881,6 +1879,16 @@ var Interception = {
1881
1879
  )
1882
1880
  );
1883
1881
  const hasDirectExtensions = normalizedDirectExtensions.length > 0;
1882
+ const blockedExtensionsSet = new Set(blockedExtensions);
1883
+ const directOnlyExtensions = normalizedDirectExtensions.filter((ext) => !blockedExtensionsSet.has(ext));
1884
+ const directRouteMatchers = [
1885
+ createDomainsRegex(normalizedDirectDomains),
1886
+ createExtensionsRegex(directOnlyExtensions)
1887
+ ].filter(Boolean);
1888
+ const blockRouteMatchers = [createExtensionsRegex(blockedExtensions)].filter(Boolean);
1889
+ const hasDirectRules = directRouteMatchers.length > 0;
1890
+ const hasBlockRules = blockRouteMatchers.length > 0;
1891
+ const hasInterceptionRules = hasDirectRules || hasBlockRules;
1884
1892
  const enabledCategories = [];
1885
1893
  if (mergedBlockingConfig.blockArchive) enabledCategories.push("\u538B\u7F29\u5305");
1886
1894
  if (mergedBlockingConfig.blockExecutable) enabledCategories.push("\u53EF\u6267\u884C\u6587\u4EF6");
@@ -1894,110 +1902,83 @@ var Interception = {
1894
1902
  if (hasDirectDomains) directRules.push(`\u76F4\u8FDE\u57DF\u540D: [${normalizedDirectDomains.length} \u4E2A]`);
1895
1903
  if (hasDirectExtensions) directRules.push(`\u76F4\u8FDE\u6269\u5C55\u540D: [${normalizedDirectExtensions.join(", ")}]`);
1896
1904
  logger9.start("setup", directRules.length > 0 ? `${directRules.join(" | ")} | \u5C4F\u853D: [${enabledCategories.join(", ")}]` : `\u4EC5\u8D44\u6E90\u5C4F\u853D\u6A21\u5F0F | \u5C4F\u853D: [${enabledCategories.join(", ")}]`);
1897
- await page.route("**/*", async (route) => {
1898
- let handled = false;
1905
+ if (!hasInterceptionRules) {
1906
+ logger9.info("\u65E0\u547D\u4E2D\u89C4\u5219\uFF0C\u8DF3\u8FC7 page.route \u6CE8\u518C");
1907
+ return;
1908
+ }
1909
+ const directRouteHandler = async (route) => {
1899
1910
  try {
1900
1911
  const request = route.request();
1901
1912
  const url = request.url();
1902
1913
  const urlLower = url.toLowerCase();
1903
1914
  const urlPath = urlLower.split("?")[0];
1904
- const interceptionEnabled = typeof enable === "function" ? Boolean(enable()) : Boolean(enable);
1905
- if (!interceptionEnabled) {
1906
- await safeContinue(route);
1907
- handled = true;
1908
- return;
1909
- }
1910
1915
  const isSilent = DirectConfig.silentExtensions.some((ext) => urlPath.endsWith(ext));
1911
- const shouldBlock = blockedExtensions.some((ext) => urlPath.endsWith(ext));
1912
- if (shouldBlock) {
1913
- await route.abort();
1914
- handled = true;
1915
- return;
1916
- }
1917
- let isDirectByDomain = false;
1918
- if (hasDirectDomains) {
1919
- try {
1920
- const hostname = new URL(url).hostname;
1921
- isDirectByDomain = normalizedDirectDomains.some((domain) => hostname.startsWith(domain));
1922
- } catch (e) {
1923
- }
1924
- }
1925
- const isDirectByExtension = hasDirectExtensions ? normalizedDirectExtensions.some((ext) => urlPath.endsWith(ext)) : false;
1926
- const isDirect = isDirectByDomain || isDirectByExtension;
1927
- if (isDirect) {
1928
- try {
1929
- const reqHeaders = await request.allHeaders();
1930
- delete reqHeaders["host"];
1931
- const resolvedAcceptLanguage = reqHeaders["accept-language"] || "";
1932
- const userAgent = reqHeaders["user-agent"] || "";
1933
- const method = request.method();
1934
- const postData = method !== "GET" && method !== "HEAD" ? request.postDataBuffer() : void 0;
1935
- const response = await (0, import_got_scraping.gotScraping)({
1936
- ...SHARED_GOT_OPTIONS,
1937
- // 应用通用配置
1938
- url,
1939
- method,
1940
- headers: reqHeaders,
1941
- body: postData,
1942
- responseType: "buffer",
1943
- // 强制获取 Buffer
1944
- // 移除手动 TLS 指纹配置,使用 got-scraping 默认的高质量指纹
1945
- // headerGeneratorOptions: ...
1946
- // 使用共享的 Agent 单例(keepAlive: false,不会池化连接)
1947
- agent: {
1948
- http: SHARED_HTTP_AGENT,
1949
- https: SHARED_HTTPS_AGENT
1950
- },
1951
- // 超时时间
1952
- timeout: { request: DirectConfig.directTimeout * 1e3 }
1953
- });
1954
- const resHeaders = {};
1955
- for (const [key, value] of Object.entries(response.headers)) {
1956
- if (Array.isArray(value)) {
1957
- resHeaders[key] = value.join(", ");
1958
- } else if (value) {
1959
- resHeaders[key] = String(value);
1960
- }
1961
- }
1962
- delete resHeaders["content-encoding"];
1963
- delete resHeaders["content-length"];
1964
- delete resHeaders["transfer-encoding"];
1965
- delete resHeaders["connection"];
1966
- delete resHeaders["keep-alive"];
1967
- isSilent ? logger9.debug(`\u76F4\u8FDE\u6210\u529F: ${urlPath}`) : logger9.info(`\u76F4\u8FDE\u6210\u529F: ${urlPath}`);
1968
- await safeFulfill(route, {
1969
- status: response.statusCode,
1970
- headers: resHeaders,
1971
- body: response.body
1972
- });
1973
- handled = true;
1974
- return;
1975
- } catch (e) {
1976
- const isTimeout = e.code === "ETIMEDOUT" || e.message.toLowerCase().includes("timeout");
1977
- const action = fallbackToProxy ? "\u56DE\u9000\u4EE3\u7406" : "\u5DF2\u653E\u5F03";
1978
- const reason = isTimeout ? `\u8D85\u65F6(${DirectConfig.directTimeout}s)` : `\u5F02\u5E38: ${e.message}`;
1979
- logger9.warn(`\u76F4\u8FDE${reason}\uFF0C${action}: ${urlPath}`);
1980
- if (fallbackToProxy) {
1981
- await safeContinue(route);
1982
- } else {
1983
- await route.abort();
1984
- }
1985
- handled = true;
1986
- return;
1916
+ const reqHeaders = await request.allHeaders();
1917
+ delete reqHeaders["host"];
1918
+ const method = request.method();
1919
+ const postData = method !== "GET" && method !== "HEAD" ? request.postDataBuffer() : void 0;
1920
+ const response = await (0, import_got_scraping.gotScraping)({
1921
+ ...SHARED_GOT_OPTIONS,
1922
+ // 应用通用配置
1923
+ url,
1924
+ method,
1925
+ headers: reqHeaders,
1926
+ body: postData,
1927
+ responseType: "buffer",
1928
+ // 强制获取 Buffer
1929
+ // 使用共享的 Agent 单例(keepAlive: false,不会池化连接)
1930
+ agent: {
1931
+ http: SHARED_HTTP_AGENT,
1932
+ https: SHARED_HTTPS_AGENT
1933
+ },
1934
+ // 超时时间
1935
+ timeout: { request: DirectConfig.directTimeout * 1e3 }
1936
+ });
1937
+ const resHeaders = {};
1938
+ for (const [key, value] of Object.entries(response.headers)) {
1939
+ if (Array.isArray(value)) {
1940
+ resHeaders[key] = value.join(", ");
1941
+ } else if (value) {
1942
+ resHeaders[key] = String(value);
1987
1943
  }
1988
1944
  }
1989
- await safeContinue(route);
1990
- handled = true;
1945
+ delete resHeaders["content-encoding"];
1946
+ delete resHeaders["content-length"];
1947
+ delete resHeaders["transfer-encoding"];
1948
+ delete resHeaders["connection"];
1949
+ delete resHeaders["keep-alive"];
1950
+ isSilent ? logger9.debug(`\u76F4\u8FDE\u6210\u529F: ${urlPath}`) : logger9.info(`\u76F4\u8FDE\u6210\u529F: ${urlPath}`);
1951
+ await safeFulfill(route, {
1952
+ status: response.statusCode,
1953
+ headers: resHeaders,
1954
+ body: response.body
1955
+ });
1991
1956
  } catch (err) {
1992
- logger9.warn(`\u8DEF\u7531\u5904\u7406\u5F02\u5E38: ${err.message}`);
1993
- if (!handled) {
1994
- try {
1995
- await route.continue();
1996
- } catch (_) {
1997
- }
1957
+ const message = String(err?.message || "");
1958
+ const isTimeout = err?.code === "ETIMEDOUT" || message.toLowerCase().includes("timeout");
1959
+ const action = fallbackToProxy ? "\u56DE\u9000\u4EE3\u7406" : "\u5DF2\u653E\u5F03";
1960
+ const reason = isTimeout ? `\u8D85\u65F6(${DirectConfig.directTimeout}s)` : `\u5F02\u5E38: ${message}`;
1961
+ logger9.warn(`\u76F4\u8FDE${reason}\uFF0C${action}`);
1962
+ if (fallbackToProxy) {
1963
+ await safeContinue(route);
1964
+ } else {
1965
+ await safeAbort(route);
1998
1966
  }
1999
1967
  }
2000
- });
1968
+ };
1969
+ const blockRouteHandler = async (route) => {
1970
+ await safeAbort(route);
1971
+ };
1972
+ if (hasDirectRules) {
1973
+ for (const matcher of directRouteMatchers) {
1974
+ await page.route(matcher, directRouteHandler);
1975
+ }
1976
+ }
1977
+ if (hasBlockRules) {
1978
+ for (const matcher of blockRouteMatchers) {
1979
+ await page.route(matcher, blockRouteHandler);
1980
+ }
1981
+ }
2001
1982
  }
2002
1983
  };
2003
1984
  async function safeFulfill(route, options) {
@@ -2017,10 +1998,37 @@ async function safeContinue(route) {
2017
1998
  }
2018
1999
  }
2019
2000
  }
2001
+ async function safeAbort(route) {
2002
+ try {
2003
+ await route.abort();
2004
+ } catch (error) {
2005
+ if (!isIgnorableError(error)) {
2006
+ }
2007
+ }
2008
+ }
2020
2009
  function isIgnorableError(error) {
2021
2010
  const msg = error.message;
2022
2011
  return msg.includes("already handled") || msg.includes("Target closed") || msg.includes("closed");
2023
2012
  }
2013
+ function createExtensionsRegex(extensions = []) {
2014
+ const normalized = Array.from(new Set(
2015
+ extensions.map((ext) => String(ext || "").toLowerCase().trim()).filter(Boolean).map((ext) => ext.startsWith(".") ? ext : `.${ext}`)
2016
+ ));
2017
+ if (!normalized.length) return null;
2018
+ const escaped = normalized.map((ext) => escapeRegex(ext));
2019
+ return new RegExp(`(?:${escaped.join("|")})(?:\\?.*)?$`, "i");
2020
+ }
2021
+ function createDomainsRegex(domains = []) {
2022
+ const normalized = Array.from(new Set(
2023
+ domains.map((domain) => String(domain || "").toLowerCase().trim()).filter(Boolean)
2024
+ ));
2025
+ if (!normalized.length) return null;
2026
+ const domainParts = normalized.map((domain) => `${escapeRegex(domain)}[^/:?#]*`);
2027
+ return new RegExp(`^https?:\\/\\/(?:${domainParts.join("|")})(?::\\d+)?(?:[/?#]|$)`, "i");
2028
+ }
2029
+ function escapeRegex(value) {
2030
+ return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2031
+ }
2024
2032
 
2025
2033
  // src/mutation.js
2026
2034
  var import_uuid2 = require("uuid");