From 674b32262a82b34e5663077075b44551c454b7d4 Mon Sep 17 00:00:00 2001 From: Tony Date: Thu, 20 Feb 2025 04:04:46 +0800 Subject: [PATCH] fix: ensure proper browser closure (#18404) --- lib/routes/aip/journal-pupp.ts | 2 +- lib/routes/alternativeto/utils.ts | 2 +- lib/routes/apkpure/versions.ts | 2 +- lib/routes/colamanga/manga.ts | 2 +- lib/routes/douyin/live.ts | 2 +- lib/routes/douyin/user.ts | 2 +- lib/routes/fortnite/news.ts | 2 +- lib/routes/gov/customs/list.ts | 2 +- lib/routes/gov/pbc/goutongjiaoliu.ts | 2 +- lib/routes/gov/pbc/trade-announcement.ts | 2 +- lib/routes/hitcon/zeroday.ts | 2 +- lib/routes/hottoys/index.ts | 4 +- lib/routes/ielts/index.ts | 2 +- lib/routes/iqiyi/video.ts | 2 +- lib/routes/njust/utils.ts | 2 +- lib/routes/nytimes/index.ts | 2 +- lib/routes/oceanengine/arithmetic-index.ts | 2 +- lib/routes/parliament.uk/commonslibrary.ts | 2 +- lib/routes/parliament.uk/lordslibrary.ts | 2 +- lib/routes/pincong/utils.ts | 2 +- lib/routes/pnas/index.ts | 2 +- lib/routes/science/blogs.ts | 4 +- lib/routes/sehuatang/index.ts | 2 +- lib/routes/spankbang/new-videos.ts | 2 +- lib/routes/sysu/ygafz.ts | 2 +- lib/routes/tiktok/user.ts | 2 +- lib/routes/uchicago/current.ts | 6 +- lib/routes/uraaka-joshi/uraaka-joshi-user.ts | 4 +- lib/routes/uraaka-joshi/uraaka-joshi.ts | 88 ++++++++++---------- lib/routes/xiaohongshu/util.ts | 4 +- lib/utils/puppeteer-utils.test.ts | 4 +- lib/utils/puppeteer.test.ts | 4 +- lib/utils/puppeteer.ts | 4 +- 33 files changed, 83 insertions(+), 87 deletions(-) diff --git a/lib/routes/aip/journal-pupp.ts b/lib/routes/aip/journal-pupp.ts index 85779d01e874cb..32f73e72bfb04f 100644 --- a/lib/routes/aip/journal-pupp.ts +++ b/lib/routes/aip/journal-pupp.ts @@ -50,7 +50,7 @@ const handler = async (ctx) => { false ); - browser.close(); + await browser.close(); return { title: jrnlName, diff --git a/lib/routes/alternativeto/utils.ts b/lib/routes/alternativeto/utils.ts index 92b1fd81f97c45..c53c34b8afe6f0 100644 --- a/lib/routes/alternativeto/utils.ts +++ b/lib/routes/alternativeto/utils.ts @@ -14,7 +14,7 @@ const puppeteerGet = (url, cache) => waitUntil: 'domcontentloaded', }); const html = await page.evaluate(() => document.documentElement.innerHTML); - browser.close(); + await browser.close(); return html; }); diff --git a/lib/routes/apkpure/versions.ts b/lib/routes/apkpure/versions.ts index 793db24b3ecb14..300c00931ac784 100644 --- a/lib/routes/apkpure/versions.ts +++ b/lib/routes/apkpure/versions.ts @@ -39,7 +39,7 @@ async function handler(ctx) { }); const r = await page.evaluate(() => document.documentElement.innerHTML); - browser.close(); + await browser.close(); const $ = load(r); const img = new URL($('.ver-top img').attr('src')); diff --git a/lib/routes/colamanga/manga.ts b/lib/routes/colamanga/manga.ts index 933e31bb95bc75..ca391d42f5491b 100644 --- a/lib/routes/colamanga/manga.ts +++ b/lib/routes/colamanga/manga.ts @@ -60,7 +60,7 @@ async function handler(ctx: Context) { }); const response = await page.content(); - browser.close(); + await browser.close(); const $ = load(response); diff --git a/lib/routes/douyin/live.ts b/lib/routes/douyin/live.ts index fb3db0ae1e66a3..3e1d05ac7dd058 100644 --- a/lib/routes/douyin/live.ts +++ b/lib/routes/douyin/live.ts @@ -58,7 +58,7 @@ async function handler(ctx) { await page.goto(pageUrl, { waitUntil: 'networkidle2', }); - browser.close(); + await browser.close(); return roomInfo; }, diff --git a/lib/routes/douyin/user.ts b/lib/routes/douyin/user.ts index 04286ef43887af..86d6284f2187e4 100644 --- a/lib/routes/douyin/user.ts +++ b/lib/routes/douyin/user.ts @@ -69,7 +69,7 @@ async function handler(ctx) { waitUntil: 'networkidle2', }); - browser.close(); + await browser.close(); if (!postData) { throw new Error('Empty post data. The request may be filtered by WAF.'); diff --git a/lib/routes/fortnite/news.ts b/lib/routes/fortnite/news.ts index 009649e660a47d..99022f6a8b0fad 100644 --- a/lib/routes/fortnite/news.ts +++ b/lib/routes/fortnite/news.ts @@ -64,7 +64,7 @@ async function handler(ctx) { }); await page.close(); - browser.close(); + await browser.close(); const { blogList: list } = data; const items = await Promise.all( diff --git a/lib/routes/gov/customs/list.ts b/lib/routes/gov/customs/list.ts index 2539ac517baca4..6473fd3f5f97c1 100644 --- a/lib/routes/gov/customs/list.ts +++ b/lib/routes/gov/customs/list.ts @@ -104,7 +104,7 @@ async function handler(ctx) { ) ); - browser.close(); + await browser.close(); return { title: `中国海关-${channelName}`, diff --git a/lib/routes/gov/pbc/goutongjiaoliu.ts b/lib/routes/gov/pbc/goutongjiaoliu.ts index 04b906c232b205..b8ce305d3d1a5b 100644 --- a/lib/routes/gov/pbc/goutongjiaoliu.ts +++ b/lib/routes/gov/pbc/goutongjiaoliu.ts @@ -75,7 +75,7 @@ async function handler() { ) ); - browser.close(); + await browser.close(); return { title: '中国人民银行 - 沟通交流', diff --git a/lib/routes/gov/pbc/trade-announcement.ts b/lib/routes/gov/pbc/trade-announcement.ts index d69333cd0cf32b..ecdfa4f6330518 100644 --- a/lib/routes/gov/pbc/trade-announcement.ts +++ b/lib/routes/gov/pbc/trade-announcement.ts @@ -68,7 +68,7 @@ async function handler() { ) ); - browser.close(); + await browser.close(); return { title: '中国人民银行 - 货币政策司公开市场交易公告', diff --git a/lib/routes/hitcon/zeroday.ts b/lib/routes/hitcon/zeroday.ts index 3d8cd77eb07c96..5cbd771a20f2b7 100644 --- a/lib/routes/hitcon/zeroday.ts +++ b/lib/routes/hitcon/zeroday.ts @@ -63,7 +63,7 @@ async function handler(ctx: Context): Promise { }); const response = await page.evaluate(() => document.documentElement.innerHTML); - browser.close(); + await browser.close(); const $ = load(response); const items: DataItem[] = $('.zdui-strip-list>li') diff --git a/lib/routes/hottoys/index.ts b/lib/routes/hottoys/index.ts index 5c21f4953fab14..a1cc08f840c543 100644 --- a/lib/routes/hottoys/index.ts +++ b/lib/routes/hottoys/index.ts @@ -39,7 +39,7 @@ async function handler() { waitUntil: 'domcontentloaded', }); const response = await page.content(); - page.close(); + await page.close(); const $ = load(response); const items = $('li.productListItem') .toArray() @@ -54,7 +54,7 @@ async function handler() { guid: a.attr('href'), }; }); - browser.close(); + await browser.close(); return { title: 'Hot Toys New Products', link: baseUrl, diff --git a/lib/routes/ielts/index.ts b/lib/routes/ielts/index.ts index 2d600b8c81e64a..cf025fb9b3aa7f 100644 --- a/lib/routes/ielts/index.ts +++ b/lib/routes/ielts/index.ts @@ -38,7 +38,7 @@ async function handler() { await page.waitForSelector('div.container'); const html = await page.evaluate(() => document.documentElement.innerHTML); - browser.close(); + await browser.close(); return html; }, config.cache.routeExpire, diff --git a/lib/routes/iqiyi/video.ts b/lib/routes/iqiyi/video.ts index 730281af5b54cf..37f9d62b6be43b 100644 --- a/lib/routes/iqiyi/video.ts +++ b/lib/routes/iqiyi/video.ts @@ -73,7 +73,7 @@ async function handler(ctx) { config.cache.routeExpire, false ); - browser.close(); + await browser.close(); return data; } diff --git a/lib/routes/njust/utils.ts b/lib/routes/njust/utils.ts index 29371a7d62c510..059210f6668b2c 100644 --- a/lib/routes/njust/utils.ts +++ b/lib/routes/njust/utils.ts @@ -23,7 +23,7 @@ async function getContent(url, pptr = false) { const content = await page.content(); return content; } finally { - browser.close(); + await browser.close(); } } else { const response = await got(url); diff --git a/lib/routes/nytimes/index.ts b/lib/routes/nytimes/index.ts index bafa23afbfa003..e3a840e892a378 100644 --- a/lib/routes/nytimes/index.ts +++ b/lib/routes/nytimes/index.ts @@ -151,7 +151,7 @@ async function handler(ctx) { }) ); - browser.close(); + await browser.close(); return { title, diff --git a/lib/routes/oceanengine/arithmetic-index.ts b/lib/routes/oceanengine/arithmetic-index.ts index b40e52ad7fecdd..d276793fd3ef5c 100644 --- a/lib/routes/oceanengine/arithmetic-index.ts +++ b/lib/routes/oceanengine/arithmetic-index.ts @@ -118,7 +118,7 @@ async function handler(ctx) { }); await page.goto('https://trendinsight.oceanengine.com/arithmetic-index'); const res = await getMultiKeywordHotTrend(page, keyword, start_date, end_date, channel); - browser.close(); + await browser.close(); const rawData = JSON.parse(res).data; const data = decrypt(rawData).hot_list[0]; diff --git a/lib/routes/parliament.uk/commonslibrary.ts b/lib/routes/parliament.uk/commonslibrary.ts index a316c64a976537..41fa182b7a914a 100644 --- a/lib/routes/parliament.uk/commonslibrary.ts +++ b/lib/routes/parliament.uk/commonslibrary.ts @@ -46,7 +46,7 @@ async function handler(ctx) { description: $(article).find('p').last().text().trim(), pubDate: timezone($(article).find('.card__date time').attr('datetime')), })); - browser.close(); + await browser.close(); return { title: `parliament - lordslibrary - ${topic}`, link: url, diff --git a/lib/routes/parliament.uk/lordslibrary.ts b/lib/routes/parliament.uk/lordslibrary.ts index bf625de82dd229..f0f07beda52641 100644 --- a/lib/routes/parliament.uk/lordslibrary.ts +++ b/lib/routes/parliament.uk/lordslibrary.ts @@ -46,7 +46,7 @@ async function handler(ctx) { description: $(article).find('p').last().text().trim(), pubDate: timezone($(article).find('.card__date time').attr('datetime')), })); - browser.close(); + await browser.close(); return { title: `parliament - lordslibrary - ${topic}`, link: url, diff --git a/lib/routes/pincong/utils.ts b/lib/routes/pincong/utils.ts index b5d901d73bf48e..db5744aaca4aca 100644 --- a/lib/routes/pincong/utils.ts +++ b/lib/routes/pincong/utils.ts @@ -14,7 +14,7 @@ const puppeteerGet = (url, cache) => waitUntil: 'domcontentloaded', }); const html = await page.evaluate(() => document.documentElement.innerHTML); - browser.close(); + await browser.close(); return html; }); diff --git a/lib/routes/pnas/index.ts b/lib/routes/pnas/index.ts index 735b01ad80005a..f66160ae02b79b 100644 --- a/lib/routes/pnas/index.ts +++ b/lib/routes/pnas/index.ts @@ -108,7 +108,7 @@ async function handler(ctx) { ) ); - browser.close(); + await browser.close(); return { title: `${$('.banner-widget__content h1').text()} - PNAS`, diff --git a/lib/routes/science/blogs.ts b/lib/routes/science/blogs.ts index a993dc53fa4806..1ddd29ec81f8cb 100644 --- a/lib/routes/science/blogs.ts +++ b/lib/routes/science/blogs.ts @@ -52,8 +52,8 @@ async function handler(ctx) { const response = await page.content(); - page.close(); - browser.close(); + await page.close(); + await browser.close(); return response; }, config.cache.routeExpire, diff --git a/lib/routes/sehuatang/index.ts b/lib/routes/sehuatang/index.ts index 17467d694d4d5e..a96efde1fa9def 100644 --- a/lib/routes/sehuatang/index.ts +++ b/lib/routes/sehuatang/index.ts @@ -80,7 +80,7 @@ async function handler(ctx) { await Promise.all([page.click('a.enter-btn'), page.waitForNavigation({ waitUntil: 'domcontentloaded' })]); const response = await page.content(); - page.close(); + await page.close(); const $ = load(response); diff --git a/lib/routes/spankbang/new-videos.ts b/lib/routes/spankbang/new-videos.ts index 1e69748f7aca11..182de368a2a0ef 100644 --- a/lib/routes/spankbang/new-videos.ts +++ b/lib/routes/spankbang/new-videos.ts @@ -61,7 +61,7 @@ const handler = async () => { false ); - browser.close(); + await browser.close(); return { title: data.title, diff --git a/lib/routes/sysu/ygafz.ts b/lib/routes/sysu/ygafz.ts index dfc74a5fba75e0..c056329bc5a041 100644 --- a/lib/routes/sysu/ygafz.ts +++ b/lib/routes/sysu/ygafz.ts @@ -63,7 +63,7 @@ async function handler(ctx) { return jar; }, cookieJar); - browser.close(); + await browser.close(); const $ = load(response); const list = $('.list-content a') diff --git a/lib/routes/tiktok/user.ts b/lib/routes/tiktok/user.ts index 5fac463f237074..c54bd80f72b92f 100644 --- a/lib/routes/tiktok/user.ts +++ b/lib/routes/tiktok/user.ts @@ -53,7 +53,7 @@ async function handler(ctx) { waitUntil: 'networkidle0', }); const SIGI_STATE = await page.evaluate(() => window.SIGI_STATE); - browser.close(); + await browser.close(); const lang = SIGI_STATE.AppContext.lang; const SharingMetaState = SIGI_STATE.SharingMetaState; diff --git a/lib/routes/uchicago/current.ts b/lib/routes/uchicago/current.ts index b27ddd679ff377..3d7516d38353b2 100644 --- a/lib/routes/uchicago/current.ts +++ b/lib/routes/uchicago/current.ts @@ -46,7 +46,7 @@ async function handler(ctx) { }); const response = await page.evaluate(() => document.documentElement.innerHTML); const cookies = await getCookies(page); - page.close(); + await page.close(); const $ = load(response); const list = $('.issue-item__title') @@ -68,7 +68,7 @@ async function handler(ctx) { referer: link, }); const response = await page.evaluate(() => document.documentElement.innerHTML); - page.close(); + await page.close(); const $ = load(response); @@ -94,7 +94,7 @@ async function handler(ctx) { ) ); - browser.close(); + await browser.close(); return { title: $('head title').text(), diff --git a/lib/routes/uraaka-joshi/uraaka-joshi-user.ts b/lib/routes/uraaka-joshi/uraaka-joshi-user.ts index f21851e460b5eb..b675dd0b8be240 100644 --- a/lib/routes/uraaka-joshi/uraaka-joshi-user.ts +++ b/lib/routes/uraaka-joshi/uraaka-joshi-user.ts @@ -42,9 +42,9 @@ async function handler(ctx) { page.on('request', (request) => { request.resourceType() === 'document' || request.resourceType() === 'script' || request.resourceType() === 'fetch' ? request.continue() : request.abort(); }); - page.on('requestfinished', (request) => { + page.on('requestfinished', async (request) => { if (request.url() === link && request.response().status() === 403) { - page.close(); + await page.close(); } }); diff --git a/lib/routes/uraaka-joshi/uraaka-joshi.ts b/lib/routes/uraaka-joshi/uraaka-joshi.ts index f1f927fbb1c75f..008c17828fe2fb 100644 --- a/lib/routes/uraaka-joshi/uraaka-joshi.ts +++ b/lib/routes/uraaka-joshi/uraaka-joshi.ts @@ -28,9 +28,9 @@ async function handler() { page.on('request', (request) => { request.resourceType() === 'document' || request.resourceType() === 'script' || request.resourceType() === 'fetch' ? request.continue() : request.abort(); }); - page.on('requestfinished', (request) => { + page.on('requestfinished', async (request) => { if (request.url() === link && request.response().status() === 403) { - page.close(); + await page.close(); } }); @@ -57,49 +57,45 @@ async function handler() { return { title, link, - item: - list && - list - .map((index, item) => { - item = $(item); - - // remove event and styles - item.find('*').removeAttr('onclick'); - item.find('*').removeAttr('onerror'); - item.find('*').removeAttr('style'); - - // format account style - const account = item.find('.account-group-link-row'); - account.html(account.text()); - - // extract video tag from its player - item.find('.plyr--video').each((_, player) => { - player = $(player); - - const video = player.find('video'); - player.replaceWith(video); - const poster = video.attr('data-poster'); - video.attr('poster', 'https:' + poster); - - const source = video.find('source'); - const src = source.attr('src'); - source.attr('src', 'https:' + src); - }); - - // correct src of img tags - item.find('img').each((_, image) => { - const src = $(image).attr('data-src'); - $(image).attr('src', 'https:' + src); - }); - - return { - title: item.find('.account-group').text() + ` - ${title}`, - description: item.html(), - link: item.find('.account-group-link-row').attr('href'), - pubDate: parseDate(item.find('.profile-char').attr('datetime')), - guid: item.find('a.tap-image').attr('data-tweet-id') || item.find('video[class^="js-player-"]').attr('data-tweet-id') || parseDate(item.find('.profile-char').attr('datetime')).getTime(), - }; - }) - .get(), + item: list.toArray().map((item) => { + item = $(item); + + // remove event and styles + item.find('*').removeAttr('onclick'); + item.find('*').removeAttr('onerror'); + item.find('*').removeAttr('style'); + + // format account style + const account = item.find('.account-group-link-row'); + account.html(account.text()); + + // extract video tag from its player + item.find('.plyr--video').each((_, player) => { + player = $(player); + + const video = player.find('video'); + player.replaceWith(video); + const poster = video.attr('data-poster'); + video.attr('poster', 'https:' + poster); + + const source = video.find('source'); + const src = source.attr('src'); + source.attr('src', 'https:' + src); + }); + + // correct src of img tags + item.find('img').each((_, image) => { + const src = $(image).attr('data-src'); + $(image).attr('src', 'https:' + src); + }); + + return { + title: item.find('.account-group').text() + ` - ${title}`, + description: item.html(), + link: item.find('.account-group-link-row').attr('href'), + pubDate: parseDate(item.find('.profile-char').attr('datetime')), + guid: item.find('a.tap-image').attr('data-tweet-id') || item.find('video[class^="js-player-"]').attr('data-tweet-id') || parseDate(item.find('.profile-char').attr('datetime')).getTime(), + }; + }), }; } diff --git a/lib/routes/xiaohongshu/util.ts b/lib/routes/xiaohongshu/util.ts index 50bd213822ea84..d35d48a0193f49 100644 --- a/lib/routes/xiaohongshu/util.ts +++ b/lib/routes/xiaohongshu/util.ts @@ -71,7 +71,7 @@ const getUser = (url, cache) => return { userPageData, notes, collect }; } finally { - browser.close(); + await browser.close(); } }, config.cache.routeExpire, @@ -95,7 +95,7 @@ const getBoard = (url, cache) => const initialSsrState = await page.evaluate(() => (window as any).__INITIAL_SSR_STATE__); return initialSsrState.Main; } finally { - browser.close(); + await browser.close(); } }, config.cache.routeExpire, diff --git a/lib/utils/puppeteer-utils.test.ts b/lib/utils/puppeteer-utils.test.ts index edd261a74319e5..8916c6aad2c7d3 100644 --- a/lib/utils/puppeteer-utils.test.ts +++ b/lib/utils/puppeteer-utils.test.ts @@ -5,9 +5,9 @@ import type { Browser } from 'puppeteer'; let browser: Browser | null = null; -afterEach(() => { +afterEach(async () => { if (browser) { - browser.close(); + await browser.close(); browser = null; } diff --git a/lib/utils/puppeteer.test.ts b/lib/utils/puppeteer.test.ts index ce77809fa3a446..1fd8f1d5aef62e 100644 --- a/lib/utils/puppeteer.test.ts +++ b/lib/utils/puppeteer.test.ts @@ -4,12 +4,12 @@ import { type Browser } from 'puppeteer'; let browser: Browser | null = null; -afterEach(() => { +afterEach(async () => { if (browser) { // double insurance to close unclosed browser immediately after each test // if a test closure fails before it can close the browser, the browser process will probably be unclosed, // especially when the test unit is run through `npm run vitest puppeteer` - browser.close(); + await browser.close(); browser = null; } delete process.env.PROXY_URI; diff --git a/lib/utils/puppeteer.ts b/lib/utils/puppeteer.ts index 24c36163244490..fe261c11f3d56f 100644 --- a/lib/utils/puppeteer.ts +++ b/lib/utils/puppeteer.ts @@ -54,8 +54,8 @@ const outPuppeteer = async ( } : options )); - setTimeout(() => { - browser.close(); + setTimeout(async () => { + await browser.close(); }, 30000); return browser;