fix(server): allow LAN/private hosts in asset reachability probe - #3103
Conversation
The reachability probe `url_fails()` short-circuited on `_is_private_address()`: any URL whose host resolved into a private / loopback / link-local range was marked un-reachable without ever being fetched. A sibling Docker container (resolving to a 172.16.0.0/12 bridge address), a NAS on 192.168.x.x, or any intranet host was therefore flagged dead even though it served HTTP 200 fine. Serving signage from the LAN is a first-class Anthias use case, so remove the guard entirely (the public demo node it protected has been retired). `url_fails()` now probes private hosts exactly like any public host, fixing both the periodic `revalidate_asset_urls` sweep and the create-time reachability check. Fixes #3101 Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR fixes asset reachability checks for LAN/private-hosted content by removing the private-address short-circuit in url_fails(), so HTTP(S) assets served from intranet/Docker/NAS hosts are actually probed and no longer incorrectly marked unreachable (Fixes #3101).
Changes:
- Removed the private-address SSRF guard (
_is_private_address) and related imports/env var handling fromurl_fails()so LAN/private hosts are fetched like public hosts. - Replaced the SSRF-guard unit tests with a regression test asserting
url_fails()probes (callsrequests.head) and returnsFalsefor a reachable LAN host.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/anthias_common/utils.py |
Removes private-host short-circuit from url_fails() so LAN/private assets are probed normally. |
tests/test_utils.py |
Updates tests to validate LAN/private host probing behavior instead of SSRF blocking behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Collapse the private-host reachability test onto the existing requests.head-mocking pattern. The reachable-verdict case is already covered by test_url_fails_returns_false_on_2xx_response; this test now only guards the distinct behaviour (no private-address short-circuit) by asserting the probe actually fires. Drops the misleading urlunparse/_FAKE_PRIVATE_HTTP scaffolding that implied a private-only code path. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Avoid a hardcoded CIDR literal in the comment, matching this file's convention of keeping static analyzers' hardcoded-IP rules quiet. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Annotate the clear-text http:// test literal with NOSONAR(S5332), matching the repo convention (see tests/test_youtube_helper.py). The URL is mocked and never fetched, so the clear-text-transport hotspot is a false positive; this clears the SonarCloud new-hotspots gate. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
On-device validation (x86 testbed)Reproduced the reporter's exact topology and verified the fix end-to-end through the integrated stack (server API → Celery reachability → viewer), not a unit harness. Setup — a sibling Before the fix (guard present, stock image):
After the fix (patched
Note: a headless Validated on x86; the changed code is board-independent Python (no board-specific branches), so behaviour is identical on the reporter's Pi 5. Testbed restored to its prior state afterwards. |



Issues Fixed
Fixes #3101
Description
Assets served from a LAN host were incorrectly failing the reachability check and going dark, even though the host returned HTTP 200 from inside every container.
The probe
url_fails()short-circuited on_is_private_address(): any URL whose host resolved into a private / loopback / link-local range was marked un-reachable without ever being fetched. A sibling Docker container (which resolves to a172.16.0.0/12bridge address, e.g. the reporter'smenu-webserver), a NAS on192.168.x.x, or any intranet host was therefore flagged dead. The periodicrevalidate_asset_urlssweep then setis_reachable=False, the viewer logged "is not available, skipping" and fired a recheck loop that re-failed for the same reason.Serving signage from the LAN is a first-class Anthias use case, so this removes the private-address guard entirely — the only place its SSRF concern applied was the public demo node, which has been retired.
url_fails()now probes private hosts exactly like any public host, fixing both the periodic sweep and the create-time reachability check._is_private_address()and the private-address branch inurl_fails()(src/anthias_common/utils.py); dropped the now-unusedipaddress/socketimports and theANTHIAS_ALLOW_PRIVATE_FETCHenv var.url_fails() is Falseand that the probe actually runs (tests/test_utils.py).Checklist