[fix] engine mullvadleta - ignore HTTP 403 & 429 response

It doesn't matter if you're using Mullvad's VPN and a proper browser, you'll
still get blocked for specific searches [1] with a 403 or 429 HTTP status code.
Mullvad only blocks the search request and doesn't prevent you from doing more
searches.

The logic should handle the blocked requests (403, 429), but not put the engine
on a cooldown.

[1] https://leta.mullvad.net/search?q=site%3Afoo+bar&engine=brave

Closes: https://github.com/searxng/searxng/issues/5328
Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
This commit is contained in:
Markus Heiser 2025-10-17 16:57:41 +02:00 committed by Markus Heiser
parent a6bb1ecf87
commit e840e3f960

View File

@ -43,9 +43,12 @@ import babel
from httpx import Response from httpx import Response
from lxml import html from lxml import html
from searx.enginelib.traits import EngineTraits from searx.enginelib.traits import EngineTraits
from searx.extended_types import SXNG_Response
from searx.locales import get_official_locales, language_tag, region_tag from searx.locales import get_official_locales, language_tag, region_tag
from searx.utils import eval_xpath_list from searx.utils import eval_xpath_list
from searx.result_types import EngineResults, MainResult from searx.result_types import EngineResults, MainResult
from searx.network import raise_for_httperror
search_url = "https://leta.mullvad.net" search_url = "https://leta.mullvad.net"
@ -112,7 +115,8 @@ class DataNodeResultIndices(t.TypedDict):
favicon: int favicon: int
def request(query: str, params: dict): def request(query: str, params: dict[str, t.Any]) -> None:
params["raise_for_httperror"] = False
params["method"] = "GET" params["method"] = "GET"
args = { args = {
"q": query, "q": query,
@ -136,10 +140,19 @@ def request(query: str, params: dict):
params["url"] = f"{search_url}/search/__data.json?{urlencode(args)}" params["url"] = f"{search_url}/search/__data.json?{urlencode(args)}"
return params
def response(resp: SXNG_Response) -> EngineResults:
results = EngineResults()
if resp.status_code in (403, 429):
# It doesn't matter if you're using Mullvad's VPN and a proper browser,
# you'll still get blocked for specific searches with a 403 or 429 HTTP
# status code.
# https://github.com/searxng/searxng/issues/5328#issue-3518337233
return results
# raise for other errors
raise_for_httperror(resp)
def response(resp: Response) -> EngineResults:
json_response = resp.json() json_response = resp.json()
nodes = json_response["nodes"] nodes = json_response["nodes"]
@ -159,7 +172,6 @@ def response(resp: Response) -> EngineResults:
query_items_indices = query_meta_data["items"] query_items_indices = query_meta_data["items"]
results = EngineResults()
for idx in data_nodes[query_items_indices]: for idx in data_nodes[query_items_indices]:
query_item_indices: DataNodeResultIndices = data_nodes[idx] query_item_indices: DataNodeResultIndices = data_nodes[idx]
results.add( results.add(