Skip to content

feat(http): identify Anthias outbound traffic with a User-Agent#2897

Merged
vpetersson merged 3 commits into
masterfrom
feat/anthias-user-agent
May 14, 2026
Merged

feat(http): identify Anthias outbound traffic with a User-Agent#2897
vpetersson merged 3 commits into
masterfrom
feat/anthias-user-agent

Conversation

@vpetersson
Copy link
Copy Markdown
Contributor

Issues Fixed

No tracked issue — improvement noted while reviewing the Screenly migration code.

Description

Adds anthias_common.http.AnthiasSession, a requests.Session subclass that sets User-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-level AnthiasSession, so Screenly's logs can identify migration traffic instead of seeing the default python-requests/<x.y> label. Other outbound call sites can adopt the class as needed; the deliberate Safari-UA spoof in anthias_common.utils (anti-bot bypass on user-supplied URLs) stays as-is.

Checklist

  • I have performed a self-review of my own code.
  • New and existing unit tests pass locally and on CI with my changes.
  • I have done an end-to-end test for Raspberry Pi devices.
  • I have tested my changes for x86 devices.
  • I added a documentation for the changes I have made (when necessary).

🤖 Generated with Claude Code

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>
@vpetersson vpetersson requested a review from a team as a code owner May 14, 2026 11:28
@vpetersson vpetersson self-assigned this May 14, 2026
@vpetersson vpetersson requested a review from Copilot May 14, 2026 11:28
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.py with get_user_agent() and AnthiasSession (a requests.Session subclass with the Anthias UA pre-set).
  • Switch screenly_migration to use a module-level _session = AnthiasSession() for all outbound calls.
  • Update test_screenly_migration patches from requests.get/post to _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.

Comment thread src/anthias_common/http.py Outdated
``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>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

``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>
@vpetersson vpetersson requested a review from Copilot May 14, 2026 11:43
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

@vpetersson vpetersson merged commit 9b12ade into master May 14, 2026
13 checks passed
vpetersson added a commit that referenced this pull request May 19, 2026
- 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).
vpetersson added a commit that referenced this pull request May 19, 2026
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants