feat(http): identify Anthias outbound traffic with a User-Agent#2897
Conversation
Adds ``anthias_common.http.AnthiasSession``, a ``requests.Session`` subclass that sets ``Anthias/<release> (+https://anthias.screenly.io)`` on every outbound call, and routes the Screenly migration paths (``validate_token``, ``ensure_asset_group``, ``migrate_asset``) through a module-level session. Other call sites can adopt it without further plumbing; the URL-availability probe that spoofs a Safari UA to dodge anti-bot pages stays as-is. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Introduces a small shared HTTP layer (anthias_common.http.AnthiasSession) that sets a canonical User-Agent: Anthias/<release> (+https://anthias.screenly.io) on outbound requests, and routes the Screenly migration helper (validate_token, ensure_asset_group, migrate_asset) through a module-level instance so Screenly's logs can identify migration traffic. Existing tests are updated to patch the new session methods instead of requests.get/requests.post, and a new test asserts the session's User-Agent shape.
Changes:
- Add
anthias_common/http.pywithget_user_agent()andAnthiasSession(arequests.Sessionsubclass with the Anthias UA pre-set). - Switch
screenly_migrationto use a module-level_session = AnthiasSession()for all outbound calls. - Update
test_screenly_migrationpatches fromrequests.get/postto_session.get/post, and add a UA-shape assertion.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/anthias_common/http.py | New shared AnthiasSession plus get_user_agent() helper sourcing the release via diagnostics. |
| src/anthias_server/lib/screenly_migration.py | Replaces direct requests calls with a module-level AnthiasSession. |
| src/anthias_server/api/tests/test_screenly_migration.py | Repoints mocks to _session.get/post and adds a UA assertion test. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
``anthias_common.http`` previously reached up into ``anthias_server.lib.diagnostics`` for the release string, inverting the layering ``anthias_common`` is supposed to have (it's already imported by both ``anthias_server`` and ``anthias_viewer``; the viewer would otherwise drag in Django via diagnostics if it ever adopted ``AnthiasSession``). Move the pure version-reader (importlib.metadata + pyproject.toml fallback, both stdlib) to ``anthias_common.version`` and re-export from the old diagnostics path so existing call sites keep working. Per #2897 Copilot review. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
``ruff format`` only. Left over from removing get_anthias_release out of this file in the previous commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
- Route HEAD probe + streaming GET through ``AnthiasSession`` so origins see the project-wide ``Anthias/<release>`` UA (#2897). - Drop the ``urllib3`` logger level side effect at import time. - Trust the serializer-stamped ``Asset.uri`` exclusively; refuse the task on an empty uri rather than guessing the extension (which could diverge from the HEAD-probed choice).
…line (#2912) * feat(server,api): auto-download remote video URLs into the asset pipeline - Detect http(s) single-file video URLs in CreateAssetSerializerMixin (ext-first, HEAD-probe fallback) and rewrite the row to a local destination + is_processing=True (v1.2 / v2 only). - New download_remote_video_asset Celery task streams via requests with a 5 GiB cap and chains into normalize_video_asset for the per-board HW-codec gate. - Live streams (RTSP / RTMP / HLS / DASH / SmoothStreaming) stay as literal URIs the viewer plays directly. - Failures land as metadata.error_message + is_processing=False via a copy-paste of the YouTube download task's on_failure contract. Closes #2894 * refactor(remote_video): apply review fixes - Route HEAD probe + streaming GET through ``AnthiasSession`` so origins see the project-wide ``Anthias/<release>`` UA (#2897). - Drop the ``urllib3`` logger level side effect at import time. - Trust the serializer-stamped ``Asset.uri`` exclusively; refuse the task on an empty uri rather than guessing the extension (which could diverge from the HEAD-probed choice). * test(remote_video): type-annotate destination-path tests for mypy CI's mypy step rejected ``test_remote_video_destination_path_*`` — ``tmp_path`` was unannotated and the literal ``{'assetdir': str}`` arg failed against ``AnthiasSettings | None``. Cast through ``AnthiasSettings`` (a ``UserDict[str, Any]``) so mypy is happy without spinning up the real config layer that needs ``HOME`` set. * refactor(remote_video): address SonarCloud findings - Extract ``_stream_remote_video_to_file`` + ``_validate_remote_video_response`` helpers so ``download_remote_video_asset`` lands under SonarCloud's cognitive- complexity ceiling. - Drop redundant ``requests.RequestException`` from the except clause — it's a subclass of ``OSError`` so ``except OSError`` already covers it (S5713). - Drop the redundant ``startswith(('http://', 'https://'))`` in the serializer; ``is_downloadable_remote_video`` already rejects every non-http(s) scheme. Removes the literal ``http://`` hotspot in mixins.py. - Replace ``udp://239.0.0.1:1234`` with ``udp://stream.example.test:1234`` in the test fixture (S1313 hardcoded IP). - Annotate the deliberate ``http://`` test case with ``# NOSONAR`` and a comment explaining the LAN-without-TLS use case. * refactor: collapse duplicate blocks flagged by SonarCloud - Extract ``_DownloadAssetTask`` base for the YouTube and remote- video download tasks. Subclasses override ``_failure_log_prefix`` only — the metadata-error / notify body lives in one place. - Merge ``test_create_remote_hls_manifest_stays_as_stream_url`` and ``test_create_rtsp_url_stays_as_stream_url`` into a single parametrized test that asserts both shapes through the same path. Brings new-code duplication below SonarCloud's 3% gate.



Issues Fixed
No tracked issue — improvement noted while reviewing the Screenly migration code.
Description
Adds
anthias_common.http.AnthiasSession, arequests.Sessionsubclass that setsUser-Agent: Anthias/<release> (+https://anthias.screenly.io)on every outbound call. The Screenly migration helper (validate_token,ensure_asset_group,migrate_asset) now routes through a module-levelAnthiasSession, so Screenly's logs can identify migration traffic instead of seeing the defaultpython-requests/<x.y>label. Other outbound call sites can adopt the class as needed; the deliberate Safari-UA spoof inanthias_common.utils(anti-bot bypass on user-supplied URLs) stays as-is.Checklist
🤖 Generated with Claude Code