From f0cfaa8e3a5f481bbab42c93316f0bcddbe05da8 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sun, 27 Sep 2026 13:48:36 +0800 Subject: [PATCH] fix: correct IMDb and TheAudioDB network probes --- app/application/nettest/catalogue.py | 11 +++++- tests/test_system_nettest.py | 56 ++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/app/application/nettest/catalogue.py b/app/application/nettest/catalogue.py index 5599b5337..7f9f81b47 100644 --- a/app/application/nettest/catalogue.py +++ b/app/application/nettest/catalogue.py @@ -352,10 +352,17 @@ def _build_external_media_rules(settings: SettingsReader) -> list[NetworkTestRul id="imdb_graphql", name="IMDb GraphQL 服务", icon="imdb", - url="https://caching.graphql.imdb.com", + url="https://caching.graphql.imdb.com/", proxy=True, allowed_redirect_prefixes=("https://caching.graphql.imdb.com/",), module_ids=("ImdbModule",), + http_method="POST", + request_json=(("query", "{ __typename }"),), + headers=( + ("Accept", "application/graphql+json, application/json"), + ("Content-Type", "application/json"), + ("x-imdb-client-name", "imdb-web-next-localized"), + ), ), ] @@ -385,7 +392,7 @@ def _build_music_service_rules() -> list[NetworkTestRule]: id="theaudiodb_api", name="TheAudioDB 音乐信息", icon="theaudiodb", - url=("https://www.theaudiodb.com/api/v1/json/2/searchalbum.php?s=radiohead"), + url=("https://www.theaudiodb.com/api/v1/json/123/search.php?s=coldplay"), proxy=True, allowed_redirect_prefixes=("https://www.theaudiodb.com/",), module_ids=("TheAudioDbModule",), diff --git a/tests/test_system_nettest.py b/tests/test_system_nettest.py index c02e640b8..8e9b6379f 100644 --- a/tests/test_system_nettest.py +++ b/tests/test_system_nettest.py @@ -265,6 +265,62 @@ class TestNettestSecurity: assert any(item["id"] == "github_proxy_web" for item in resp.data) assert all(set(item) == {"id", "name", "address", "icon"} for item in resp.data) + def test_nettest_imdb_graphql_uses_post_probe(self): + """IMDb GraphQL 探测应使用模块客户端采用的 POST 请求格式。""" + captured = {} + response = SimpleNamespace( + status_code=200, + headers={}, + text='{"data":{"__typename":"Query"}}', + aclose=AsyncMock(), + ) + + async def respond(method, url, **options): + """记录 IMDb 探测请求并返回成功响应。""" + captured.update(method=method, url=url, **options) + return response + + transport = SimpleNamespace(request=AsyncMock(side_effect=respond)) + result = asyncio.run( + _network_test_service(transport).execute(target_id="imdb_graphql") + ) + + assert result.success + assert captured["method"] == "POST" + assert captured["url"] == "https://caching.graphql.imdb.com/" + assert captured["json_body"] == {"query": "{ __typename }"} + assert captured["headers"] == { + "Accept": "application/graphql+json, application/json", + "Content-Type": "application/json", + "x-imdb-client-name": "imdb-web-next-localized", + } + + def test_nettest_theaudiodb_uses_current_free_key_and_health_endpoint(self): + """TheAudioDB 探测应使用当前公开测试 Key 和模块连通性接口。""" + captured = {} + response = SimpleNamespace( + status_code=200, + headers={}, + text='{"artists":[]}', + aclose=AsyncMock(), + ) + + async def respond(method, url, **options): + """记录 TheAudioDB 探测请求并返回成功响应。""" + captured.update(method=method, url=url, **options) + return response + + transport = SimpleNamespace(request=AsyncMock(side_effect=respond)) + result = asyncio.run( + _network_test_service(transport).execute(target_id="theaudiodb_api") + ) + + assert result.success + assert captured["method"] == "GET" + assert captured["url"] == ( + "https://www.theaudiodb.com/api/v1/json/123/search.php?s=coldplay" + ) + def test_nettest_blocks_unknown_target_before_transport(self): """未知目标在应用服务目录匹配阶段即返回,不得触发传输端口。"""