From 76f951093f9f0eac71779b8263aca77731ea95e6 Mon Sep 17 00:00:00 2001 From: Stanislav Khromov Date: Sun, 9 Oct 2022 18:23:30 +0200 Subject: [PATCH] Timeout fixes and cleanup --- .../04_add_favicon_column/migration.sql | 2 ++ db/mysql/schema.prisma | 1 + lib/favicon.js | 35 +++++++++---------- package.json | 1 + yarn.lock | 12 +++++++ 5 files changed, 33 insertions(+), 18 deletions(-) create mode 100644 db/mysql/migrations/04_add_favicon_column/migration.sql diff --git a/db/mysql/migrations/04_add_favicon_column/migration.sql b/db/mysql/migrations/04_add_favicon_column/migration.sql new file mode 100644 index 00000000..f344c8ff --- /dev/null +++ b/db/mysql/migrations/04_add_favicon_column/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE `website` ADD COLUMN `favicon` VARCHAR(500) NULL; diff --git a/db/mysql/schema.prisma b/db/mysql/schema.prisma index 9ad2620c..0daba55a 100644 --- a/db/mysql/schema.prisma +++ b/db/mysql/schema.prisma @@ -85,6 +85,7 @@ model website { domain String? @db.VarChar(500) share_id String? @unique() @db.VarChar(64) created_at DateTime? @default(now()) @db.Timestamp(0) + favicon String? @db.VarChar(500) account account @relation(fields: [user_id], references: [user_id]) event event[] pageview pageview[] diff --git a/lib/favicon.js b/lib/favicon.js index d2ef8cb3..c39df37b 100644 --- a/lib/favicon.js +++ b/lib/favicon.js @@ -1,9 +1,6 @@ import fetch from 'node-fetch'; -import AbortController from 'abort-controller'; import { parse } from 'node-html-parser'; - -//Node.js >=14.17 only -//const AbortController = globalThis.AbortController || (await import('abort-controller')); +import { TimeoutController } from 'timeout-abort-controller'; const filterLinks = links => { const attrs = ['rel', 'href', 'sizes']; @@ -14,7 +11,7 @@ const filterLinks = links => { .map(filterAttrs); }; -const updateAttrs = url => icons => { +const formatValues = (url, icons) => { const getOrigin = url => new URL(url).origin; return icons.map(({ sizes, href, rel }) => ({ size: parseInt(sizes?.split('x')[0]) || undefined, @@ -23,28 +20,30 @@ const updateAttrs = url => icons => { })); }; -const fetchLinks = url => { - const controller = new AbortController(); - const timeout = setTimeout(() => { - // eslint-disable-next-line no-console - console.log('Aborting!'); - controller.abort(); - }, 1000); +const fetchLinks = async url => { + // Time out the favicon request if it doesn't respond in a reasonable time. + const tc = new TimeoutController(3000); + + let links = []; try { - return fetch(url, { signal: controller.signal }) - .then(res => res.text()) - .then(str => parse(str)) - .then(html => html.querySelectorAll('head link')); + const html = await (await fetch(url, { signal: tc.signal })).text(); + links = parse(html).querySelectorAll('head link'); } catch (e) { // eslint-disable-next-line no-console console.log(`Could not fetch favicon for url ${url}`, e); } finally { - clearTimeout(timeout); + tc.clear(); } + + return links; }; -const getIcons = url => fetchLinks(url).then(filterLinks).then(updateAttrs(url)); +const getIcons = async url => { + const links = await fetchLinks(url); + const icons = filterLinks(links); + return formatValues(url, icons); +}; export default async domain => { const icons = await getIcons(`https://${domain}`); diff --git a/package.json b/package.json index e48baebe..099e26d6 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "request-ip": "^3.3.0", "semver": "^7.3.6", "thenby": "^1.3.4", + "timeout-abort-controller": "^3.0.0", "timezone-support": "^2.0.2", "uuid": "^8.3.2", "zustand": "^3.7.2" diff --git a/yarn.lock b/yarn.lock index 0ecada3e..5d9a5203 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5904,6 +5904,11 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" +retimer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/retimer/-/retimer-3.0.0.tgz#98b751b1feaf1af13eb0228f8ea68b8f9da530df" + integrity sha512-WKE0j11Pa0ZJI5YIk0nflGI7SQsfl2ljihVy7ogh7DeQSeYAUi0ubZ/yEueGtDfUPk6GH5LRw1hBdLq4IwUBWA== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -6492,6 +6497,13 @@ through@2.3.8, "through@>=2.2.7 <3", through@^2.3.8: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== +timeout-abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/timeout-abort-controller/-/timeout-abort-controller-3.0.0.tgz#dd57ffca041652c03769904f8d95afd93fb95595" + integrity sha512-O3e+2B8BKrQxU2YRyEjC/2yFdb33slI22WRdUaDx6rvysfi9anloNZyR2q0l6LnePo5qH7gSM7uZtvvwZbc2yA== + dependencies: + retimer "^3.0.0" + timezone-support@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/timezone-support/-/timezone-support-2.0.2.tgz"