From 2c3a743546b7ef8164b50e3340cc1e5c76b351cd Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Thu, 16 Jul 2026 05:03:23 +0800 Subject: [PATCH] Restore reliable Baidu search verification Keep node-fetch for search engines that reject Node's global fetch, but use the global fetch implementation for Baidu, where node-fetch connections reset or hang. Bound each request and the workflow job, require HTTP 200 responses, and include the site and URL in errors. This restores Baidu coverage without allowing a live probe to consume the six-hour default. --- .../scripts/verify-search-engine-configs.mjs | 34 +++++++++++++++---- .github/workflows/verify-configs.yml | 1 + 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/.github/workflows/scripts/verify-search-engine-configs.mjs b/.github/workflows/scripts/verify-search-engine-configs.mjs index 8e6b84e49..c63eca2dd 100644 --- a/.github/workflows/scripts/verify-search-engine-configs.mjs +++ b/.github/workflows/scripts/verify-search-engine-configs.mjs @@ -1,5 +1,7 @@ import { JSDOM } from 'jsdom' -import fetch, { Headers } from 'node-fetch' +import nodeFetch from 'node-fetch' + +const REQUEST_TIMEOUT_MS = 30_000 const config = { google: { @@ -42,6 +44,7 @@ const config = { sidebarContainerQuery: ['#content_right'], appendContainerQuery: ['#container'], resultsContainerQuery: ['#content_left', '#results'], + requireSameOrigin: true, }, kagi: { inputQuery: ["input[name='q']", "textarea[name='q']"], @@ -117,11 +120,11 @@ const commonHeaders = { 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7', // for baidu } -const desktopHeaders = new Headers({ +const desktopHeaders = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/108.0.1462.76', ...commonHeaders, -}) +} const mobileHeaders = { 'User-Agent': @@ -140,16 +143,33 @@ const mobileQueryNames = ['inputQuery', 'resultsContainerQuery'] let errors = '' +function fetchSearchPage(siteName, url, options) { + // Baidu resets node-fetch requests, while Naver rejects global fetch requests. + const fetcher = siteName === 'baidu' ? globalThis.fetch : nodeFetch + return fetcher(url, options) +} + async function verify(errorTag, urls, headers, queryNames) { await Promise.all( Object.entries(urls).map(([siteName, urlArray]) => Promise.all( urlArray.map((url) => - fetch(url, { + fetchSearchPage(siteName, url, { method: 'GET', headers: headers, + signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), }) - .then((response) => response.text()) + .then((response) => { + const requestedOrigin = new URL(url).origin + const responseOrigin = new URL(response.url).origin + if (config[siteName].requireSameOrigin && responseOrigin !== requestedOrigin) { + throw new Error(`Unexpected redirect from ${requestedOrigin} to ${responseOrigin}`) + } + if (response.status !== 200) { + throw new Error(`HTTP ${response.status} ${response.statusText}`) + } + return response.text() + }) .then((text) => { const dom = new JSDOM(text) for (const queryName of queryNames) { @@ -173,7 +193,9 @@ async function verify(errorTag, urls, headers, queryNames) { } }) .catch((error) => { - errors += errorTag + error + '\n' + const errorCode = error.code ?? error.cause?.code + const errorCodeSuffix = errorCode ? ` (${errorCode})` : '' + errors += `${errorTag}${siteName} ${url}: ${error}${errorCodeSuffix}\n` }), ), ), diff --git a/.github/workflows/verify-configs.yml b/.github/workflows/verify-configs.yml index 3bcca49a6..ac9389b3f 100644 --- a/.github/workflows/verify-configs.yml +++ b/.github/workflows/verify-configs.yml @@ -7,6 +7,7 @@ on: jobs: verify_configs: runs-on: ubuntu-22.04 + timeout-minutes: 5 steps: - uses: actions/checkout@v7