From 9db32e1f194fa621d987b31bbabd611339d18762 Mon Sep 17 00:00:00 2001 From: luna Date: Wed, 8 Jul 2026 14:23:06 +0800 Subject: [PATCH 1/2] fix: use certifi for SSL certificates on macOS Python from python.org on macOS does not pre-install SSL certificates, causing all HTTPS feed fetches to fail with: SSL: CERTIFICATE_VERIFY_FAILED - unable to get local issuer certificate Fix by using the certifi package (already a transitive dependency via httpx) to provide a reliable certificate bundle across all platforms. - fetcher.py: use ssl.create_default_context(cafile=certifi.where()) for HTTPS - pyproject.toml: add certifi as direct dependency Co-Authored-By: Claude --- backend/feed_engine/fetcher.py | 12 ++++++++++-- backend/pyproject.toml | 1 + backend/uv.lock | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/backend/feed_engine/fetcher.py b/backend/feed_engine/fetcher.py index a894138..3d71d76 100644 --- a/backend/feed_engine/fetcher.py +++ b/backend/feed_engine/fetcher.py @@ -109,10 +109,12 @@ import asyncio import ssl + +import certifi from dataclasses import dataclass from urllib.error import HTTPError, URLError from urllib.parse import urlsplit -from urllib.request import Request, urlopen +from urllib.request import HTTPSHandler, Request, build_opener, urlopen from feed_engine.errors import FeedEngineError @@ -178,10 +180,16 @@ def _fetch_feed_sync( request = Request(url, headers=headers) + if url.startswith("https://"): + ssl_context = ssl.create_default_context(cafile=certifi.where()) + opener = build_opener(HTTPSHandler(context=ssl_context)) + else: + opener = build_opener() + print("[FETCH START]", url) try: - with urlopen(request, timeout=timeout_seconds) as response: + with opener.open(request, timeout=timeout_seconds) as response: print("[FETCH OK]", response.status) return FetchResponse( diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 4125203..63d7e0a 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -66,6 +66,7 @@ dependencies = [ "bleach>=6.2", "lxml>=5.3", "markdownify>=1.1", + "certifi>=2024", ] [dependency-groups] diff --git a/backend/uv.lock b/backend/uv.lock index 7718381..1b79e30 100644 --- a/backend/uv.lock +++ b/backend/uv.lock @@ -338,6 +338,7 @@ source = { virtual = "." } dependencies = [ { name = "beautifulsoup4" }, { name = "bleach" }, + { name = "certifi" }, { name = "fastapi" }, { name = "httpx" }, { name = "lxml" }, @@ -362,6 +363,7 @@ dev = [ requires-dist = [ { name = "beautifulsoup4", specifier = ">=4.12" }, { name = "bleach", specifier = ">=6.2" }, + { name = "certifi", specifier = ">=2024" }, { name = "fastapi", specifier = ">=0.115" }, { name = "httpx", specifier = ">=0.27" }, { name = "lxml", specifier = ">=5.3" }, From 0c0591d5824378c05ff9484fdb3107f0439e6a6b Mon Sep 17 00:00:00 2001 From: luna Date: Wed, 8 Jul 2026 14:28:00 +0800 Subject: [PATCH 2/2] fix: sort imports and remove unused urlopen Co-Authored-By: Claude --- backend/feed_engine/fetcher.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/feed_engine/fetcher.py b/backend/feed_engine/fetcher.py index 3d71d76..6f4324f 100644 --- a/backend/feed_engine/fetcher.py +++ b/backend/feed_engine/fetcher.py @@ -109,12 +109,12 @@ import asyncio import ssl - -import certifi from dataclasses import dataclass from urllib.error import HTTPError, URLError from urllib.parse import urlsplit -from urllib.request import HTTPSHandler, Request, build_opener, urlopen +from urllib.request import HTTPSHandler, Request, build_opener + +import certifi from feed_engine.errors import FeedEngineError