diff --git a/backend/open_webui/env.py b/backend/open_webui/env.py index 96a3d2e6e4..dea7251580 100644 --- a/backend/open_webui/env.py +++ b/backend/open_webui/env.py @@ -590,6 +590,9 @@ if AIOHTTP_CLIENT_STREAM_IDLE_TIMEOUT is not None and AIOHTTP_CLIENT_STREAM_IDLE # When "True", falls back to AIOHTTP_CLIENT_SSL_CERT_FILE if set. AIOHTTP_CLIENT_SESSION_SSL = _parse_ssl_env(os.getenv('AIOHTTP_CLIENT_SESSION_SSL', 'True')) +SEARXNG_CLIENT_CERT_FILE = os.getenv('SEARXNG_CLIENT_CERT_FILE', '').strip() +SEARXNG_CLIENT_KEY_FILE = os.getenv('SEARXNG_CLIENT_KEY_FILE', '').strip() + # When False (default), outbound HTTP requests do not follow 3xx redirects. AIOHTTP_CLIENT_ALLOW_REDIRECTS = os.getenv('AIOHTTP_CLIENT_ALLOW_REDIRECTS', 'False').lower() == 'true' diff --git a/backend/open_webui/retrieval/web/searxng.py b/backend/open_webui/retrieval/web/searxng.py index 9c48b0f1b3..6b1c03cdd3 100644 --- a/backend/open_webui/retrieval/web/searxng.py +++ b/backend/open_webui/retrieval/web/searxng.py @@ -1,7 +1,10 @@ from __future__ import annotations import logging +import ssl +from functools import lru_cache +from open_webui.env import AIOHTTP_CLIENT_SESSION_SSL, SEARXNG_CLIENT_CERT_FILE, SEARXNG_CLIENT_KEY_FILE from open_webui.retrieval.web.main import SearchResult, get_filtered_results from open_webui.utils.session_pool import get_session @@ -17,6 +20,19 @@ _SEARXNG_HEADERS = { } +@lru_cache +def _get_ssl_context() -> bool | ssl.SSLContext: + if not SEARXNG_CLIENT_CERT_FILE: + return AIOHTTP_CLIENT_SESSION_SSL + + ssl_context = ssl.create_default_context() + ssl_context.load_cert_chain( + certfile=SEARXNG_CLIENT_CERT_FILE, + keyfile=SEARXNG_CLIENT_KEY_FILE or None, + ) + return ssl_context + + async def search_searxng( query_url: str, query: str, @@ -48,7 +64,12 @@ async def search_searxng( log.debug('searching %s', query_url) session = await get_session() - async with session.get(query_url, headers=_SEARXNG_HEADERS, params=params) as response: + async with session.get( + query_url, + headers=_SEARXNG_HEADERS, + params=params, + ssl=_get_ssl_context(), + ) as response: response.raise_for_status() payload = await response.json()