From fa301dcfb59107bb027021cda6f8a6308a7e6172 Mon Sep 17 00:00:00 2001 From: jakeaturner Date: Wed, 2 Sep 2026 15:55:44 +0000 Subject: [PATCH] fix(zim): extract Kiwix catalog URL into system-wide constant --- admin/app/services/kiwix_catalog_service.ts | 11 ++--------- admin/app/services/zim_service.ts | 7 ++----- admin/constants/kiwix.ts | 12 +++++++++++- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/admin/app/services/kiwix_catalog_service.ts b/admin/app/services/kiwix_catalog_service.ts index 2d172cf3..1b934088 100644 --- a/admin/app/services/kiwix_catalog_service.ts +++ b/admin/app/services/kiwix_catalog_service.ts @@ -4,6 +4,7 @@ import { DateTime } from 'luxon' import logger from '@adonisjs/core/services/logger' import InstalledResource from '#models/installed_resource' import { isRawListRemoteZimFilesResponse } from '../../util/zim.js' +import { KIWIX_CATALOG_BASE_URL } from '../../constants/kiwix.js' /** * Local, in-process freshness check for installed content (Kiwix ZIM files + @@ -24,14 +25,6 @@ import { isRawListRemoteZimFilesResponse } from '../../util/zim.js' * defensive — a malformed entry is skipped, never thrown. */ -// `browse.library.kiwix.org` is Kiwix's *human* browsing host. On 2026-08-29 it grew an -// anti-crawler interstitial that answers HTTP 200 with an HTML "Please confirm..." page -// requiring JS + a cookie, so every catalog request here returned unparseable HTML. -// `parseZimEntries` swallows that as an empty feed, which reads as "no updates available" -// -- a silent, permanent stall of ZIM auto-update. `opds.library.kiwix.org` is the -// machine-facing host for the same API and is not gated; `library.kiwix.org` now 301s to -// it. Keep catalog traffic off the browse host. -const KIWIX_CATALOG_URL = 'https://opds.library.kiwix.org/catalog/v2/entries' const GITHUB_PMTILES_URL = 'https://api.github.com/repos/Crosstalk-Solutions/project-nomad-maps/contents/pmtiles' @@ -194,7 +187,7 @@ export class KiwixCatalogService { count: number start: number }): Promise<{ entries: CatalogZimEntry[]; totalResults: number }> { - const res = await axios.get(KIWIX_CATALOG_URL, { + const res = await axios.get(KIWIX_CATALOG_BASE_URL, { params: { start: params.start, count: params.count, diff --git a/admin/app/services/zim_service.ts b/admin/app/services/zim_service.ts index a687c3be..75e761f2 100644 --- a/admin/app/services/zim_service.ts +++ b/admin/app/services/zim_service.ts @@ -38,6 +38,7 @@ import CustomLibrarySource from '#models/custom_library_source' import { assertNotPrivateUrl } from '#validators/common' import { resolveZimDownload } from '../utils/zim_download_resolution.js' import { getHostedContentHeaders } from '../utils/hosted_content_auth.js' +import { KIWIX_CATALOG_BASE_URL } from '../../constants/kiwix.js' const ZIM_MIME_TYPES = ['application/x-zim', 'application/x-openzim', 'application/octet-stream'] const WIKIPEDIA_OPTIONS_URL = 'https://raw.githubusercontent.com/Crosstalk-Solutions/project-nomad/refs/heads/main/collections/wikipedia.json' @@ -81,10 +82,6 @@ export class ZimService { count: number query?: string }): Promise { - // The machine-facing OPDS host. NOT `browse.library.kiwix.org`, which since 2026-08-29 - // serves an anti-crawler confirmation page (HTTP 200 + HTML) that fails - // `isRawListRemoteZimFilesResponse` and 500s this endpoint. See kiwix_catalog_service. - const LIBRARY_BASE_URL = 'https://opds.library.kiwix.org/catalog/v2/entries' // Kiwix returns pages of content unaware of what the user has installed locally. When // the installed set is large, a single 12-item Kiwix page can come back with everything // already installed → 0 post-filter items → frontend deadlock (#731). Accumulate across @@ -110,7 +107,7 @@ export class ZimService { let totalResults = 0 for (let i = 0; i < MAX_KIWIX_FETCHES; i++) { - const res = await axios.get(LIBRARY_BASE_URL, { + const res = await axios.get(KIWIX_CATALOG_BASE_URL, { params: { start: currentStart, count: KIWIX_PAGE_SIZE, diff --git a/admin/constants/kiwix.ts b/admin/constants/kiwix.ts index bc2504cb..20be3e60 100644 --- a/admin/constants/kiwix.ts +++ b/admin/constants/kiwix.ts @@ -1,2 +1,12 @@ -export const KIWIX_LIBRARY_CMD = '--library /data/kiwix-library.xml --monitorLibrary --address=all' \ No newline at end of file +export const KIWIX_LIBRARY_CMD = '--library /data/kiwix-library.xml --monitorLibrary --address=all' + +/** `browse.library.kiwix.org` is Kiwix's *human* browsing host. On 2026-08-29 it grew an +* anti-crawler interstitial that answers HTTP 200 with an HTML "Please confirm..." page +* requiring JS + a cookie, so every catalog request here returned unparseable HTML. +* `parseZimEntries` swallows that as an empty feed, which reads as "no updates available" +* -- a silent, permanent stall of ZIM auto-update. `opds.library.kiwix.org` is the +* machine-facing host for the same API and is not gated; `library.kiwix.org` now 301s to +* it. Keep catalog traffic off the browse host. +*/ +export const KIWIX_CATALOG_BASE_URL = 'https://opds.library.kiwix.org/catalog/v2/entries' \ No newline at end of file