@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 +103 -95
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +105 -97
- package/dist/index.js.map +3 -3
- package/index.d.ts +0 -2
- package/package.json +1 -1
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
|
-
|
|
1898
|
-
|
|
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
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
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
|
-
|
|
1990
|
-
|
|
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
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
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");
|