Skip to content

feat(proxy): auto-proxy internal addon endpoints and subtitle URLs#1029

Open
IbbyLabs wants to merge 1 commit into
Viren070:mainfrom
IbbyLabs:feat/auto-proxy-http
Open

feat(proxy): auto-proxy internal addon endpoints and subtitle URLs#1029
IbbyLabs wants to merge 1 commit into
Viren070:mainfrom
IbbyLabs:feat/auto-proxy-http

Conversation

@IbbyLabs

@IbbyLabs IbbyLabs commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Two related proxy changes:

  • Auto-route addon stream and subtitle URLs whose host is an internal container hostname or private IP (e.g. http://nzbdav:8080) through the configured proxy. An external player can't reach a container host or private address, so these are proxied regardless of the per-addon/per-service filters.
  • Proxy subtitle URLs on demand via a subtitle proxied-service, selectable in the proxy settings and documented for the DEFAULT_PROXY_PROXIED_SERVICES / FORCE_PROXY_PROXIED_SERVICES env vars. Mirrors how stream proxying is opted into.

Supersedes #1020 (its subtitle-URL proxying is included here).

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds internal-endpoint detection for proxy decisions. Core stream and subtitle handling now use it to widen proxying, and frontend addon install/edit flows now derive and apply proxy configuration automatically for internal addon manifests.

Changes

Auto-proxy for internal addon endpoints

Layer / File(s) Summary
isInternalEndpoint utility
packages/core/src/utils/http.ts
Adds isInternalEndpoint(url: URL): boolean with hostname heuristics for local, private, IPv6, and bootstrap-configured endpoints.
Backend stream proxification
packages/core/src/streams/proxifier.ts
Treats http: streams on internal endpoints as proxyable when proxying is enabled.
Backend subtitle proxification
packages/core/src/main/resources.ts
Adds per-addon subtitle URL proxification with allowlist checks, error fallback, and updated getSubtitles aggregation.
Frontend proxy-auto utilities
packages/frontend/src/components/menu/addons/_components/proxy-auto.ts
Adds manifest URL normalisation, internal-endpoint detection, auto-proxy decision logic, and proxy-state application helpers.
Frontend addon UI integration
packages/frontend/src/components/menu/addons/index.tsx, packages/frontend/src/components/menu/addons/_components/my-addons.tsx
Uses the new helpers in addon install/edit and manifest update flows, updates user data through proxy-aware paths, and shows conditional informational toasts.

Estimated code review effort: 4 (Complex) | ~50 minutes

Suggested reviewers: Viren070

Poem

🐇 I hop through tunnels, brisk and light,
Local add-ons glow in proxy night.
Streams and subtitles take the route,
With rabbit wisdom neatly put.
A manifest says, “I’m home, I’m near,”
And proxy paths appear.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: automatic proxying for internal addon endpoints and subtitle URLs.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
packages/frontend/src/components/menu/addons/_components/my-addons.tsx (1)

1026-1068: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Same autoEnabledProxy timing issue as in index.tsx.

The autoEnabledProxy variable is assigned inside the setUserData callback (line 1052) but used outside for toast display (line 1059). This has the same potential race condition as the add/edit flows in index.tsx.

Apply the same fix pattern: compute autoEnabledProxy synchronously before calling setUserData.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/frontend/src/components/menu/addons/_components/my-addons.tsx`
around lines 1026 - 1068, The variable `autoEnabledProxy` is being assigned
inside the `setUserData` callback function, but then used immediately after to
conditionally display toast messages, which creates a race condition since state
updates are asynchronous. Move the `applyInternalAddonProxyConfig` call outside
the `setUserData` callback and compute `autoEnabledProxy` synchronously before
calling `setUserData`, then pass the computed result to the state setter to
ensure the variable is available for the toast logic that checks if
`autoEnabledProxy` is true.
packages/frontend/src/components/menu/addons/index.tsx (1)

270-305: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Same autoEnabledProxy timing issue in edit flow.

The edit flow has the same potential race condition as the add flow - autoEnabledProxy is assigned inside the setUserData callback but used outside it for toast display.

Apply the same fix pattern as suggested for the add flow.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/frontend/src/components/menu/addons/index.tsx` around lines 270 -
305, The autoEnabledProxy variable is assigned inside the setUserData state
callback but used outside it for conditional toast messages, creating a race
condition. Restructure the code to determine autoEnabledProxy before the
setUserData call by extracting the autoProxyResult assignment outside the
callback. Create the autoProxyResult from applyInternalAddonProxyConfig before
calling setUserData, then use that same result both for the state update and for
the subsequent conditional toast messages that check autoEnabledProxy.
🧹 Nitpick comments (1)
packages/frontend/src/components/menu/addons/_components/proxy-auto.ts (1)

31-56: ⚖️ Poor tradeoff

Consider extracting shared isInternalEndpoint logic to avoid duplication.

This function duplicates the logic from packages/core/src/utils/http.ts. While the frontend version omits the bootstrap URL checks (which makes sense as those configs aren't available client-side), the heuristics should stay in sync. The IPv6 detection issues noted in the core version (false positives for facebook.com, fdroid.org) also apply here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/frontend/src/components/menu/addons/_components/proxy-auto.ts`
around lines 31 - 56, The isInternalEndpoint function duplicates logic from the
core version in packages/core/src/utils/http.ts. Extract the common hostname
checking heuristics (localhost, IPv4 private ranges, IPv6 detection, etc.) into
a shared utility that both the frontend and core versions can reference to keep
them in sync. Since frontend and core have different contexts, create a shared
utility file that both packages can import from. Additionally, review and fix
the IPv6 detection logic (hostname.startsWith('fc') and
hostname.startsWith('fd')) that produces false positives for domains like
facebook.com and fdroid.org by making the patterns more strict to properly
detect link-local and unique-local IPv6 addresses instead of catching common
domain patterns.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/utils/http.ts`:
- Around line 316-321: The IPv6 address detection logic has two issues: first,
the checks for ::1 and fe80: need to account for bracket-wrapped format that
url.hostname may return (e.g., [::1] instead of ::1), and second, the string
prefix checks for fc and fd are too broad and will incorrectly match public
domains like facebook.com and fdroid.org as internal endpoints. Fix this by
either stripping brackets before checking IPv6 patterns, or adjusting the checks
to match the full bracket-wrapped format; additionally, make the ULA prefix
checks more specific by validating that they match actual IPv6 ULA addresses
(which follow the pattern of 4 hexadecimal characters followed by a colon, e.g.,
fc00: or fd00:) rather than just checking if the string starts with these
characters.

In `@packages/frontend/src/components/menu/addons/_components/proxy-auto.ts`:
- Line 1: Replace the relative path import in the import statement at the top of
proxy-auto.ts file that imports from the core package constants. Instead of
using the relative path traversal
(../../../../../../../../core/src/utils/constants), use the workspace import
alias `@aiostreams/core` to import the constants module. Update all usages of the
imported constants throughout the file to ensure they remain compatible with the
new import path.

In `@packages/frontend/src/components/menu/addons/index.tsx`:
- Around line 236-267: The variable autoEnabledProxy is being assigned inside
the setUserData callback but the toast logic that depends on it executes
synchronously afterward, causing stale closure values. Compute autoEnabledProxy
before calling setUserData by extracting the logic: first call
applyInternalAddonProxyConfig to get the autoProxyResult and extract
autoEnabledProxy, then use that result when calling setUserData and when
evaluating the toast conditions. This ensures the toast logic uses the actual
computed value rather than the initial false value.

---

Duplicate comments:
In `@packages/frontend/src/components/menu/addons/_components/my-addons.tsx`:
- Around line 1026-1068: The variable `autoEnabledProxy` is being assigned
inside the `setUserData` callback function, but then used immediately after to
conditionally display toast messages, which creates a race condition since state
updates are asynchronous. Move the `applyInternalAddonProxyConfig` call outside
the `setUserData` callback and compute `autoEnabledProxy` synchronously before
calling `setUserData`, then pass the computed result to the state setter to
ensure the variable is available for the toast logic that checks if
`autoEnabledProxy` is true.

In `@packages/frontend/src/components/menu/addons/index.tsx`:
- Around line 270-305: The autoEnabledProxy variable is assigned inside the
setUserData state callback but used outside it for conditional toast messages,
creating a race condition. Restructure the code to determine autoEnabledProxy
before the setUserData call by extracting the autoProxyResult assignment outside
the callback. Create the autoProxyResult from applyInternalAddonProxyConfig
before calling setUserData, then use that same result both for the state update
and for the subsequent conditional toast messages that check autoEnabledProxy.

---

Nitpick comments:
In `@packages/frontend/src/components/menu/addons/_components/proxy-auto.ts`:
- Around line 31-56: The isInternalEndpoint function duplicates logic from the
core version in packages/core/src/utils/http.ts. Extract the common hostname
checking heuristics (localhost, IPv4 private ranges, IPv6 detection, etc.) into
a shared utility that both the frontend and core versions can reference to keep
them in sync. Since frontend and core have different contexts, create a shared
utility file that both packages can import from. Additionally, review and fix
the IPv6 detection logic (hostname.startsWith('fc') and
hostname.startsWith('fd')) that produces false positives for domains like
facebook.com and fdroid.org by making the patterns more strict to properly
detect link-local and unique-local IPv6 addresses instead of catching common
domain patterns.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6fc80dc7-303f-4cd4-8559-92b11b0167c9

📥 Commits

Reviewing files that changed from the base of the PR and between 004e0e8 and f0411bb.

📒 Files selected for processing (6)
  • packages/core/src/main/resources.ts
  • packages/core/src/streams/proxifier.ts
  • packages/core/src/utils/http.ts
  • packages/frontend/src/components/menu/addons/_components/my-addons.tsx
  • packages/frontend/src/components/menu/addons/_components/proxy-auto.ts
  • packages/frontend/src/components/menu/addons/index.tsx

Comment thread packages/core/src/utils/http.ts Outdated
Comment thread packages/frontend/src/components/menu/addons/_components/proxy-auto.ts Outdated
Comment thread packages/frontend/src/components/menu/addons/index.tsx
@IbbyLabs IbbyLabs marked this pull request as draft June 18, 2026 22:24
@IbbyLabs IbbyLabs force-pushed the feat/auto-proxy-http branch from f0411bb to 0752166 Compare June 18, 2026 22:43
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/frontend/src/components/menu/addons/_components/my-addons.tsx (1)

1015-1025: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Do not validate auto-proxied internal manifests with a browser fetch.

Line 1017 still fetches the container/internal URL directly before the proxy update at Lines 1045-1051. For hostnames only reachable inside the self-hosted network, this fails and returns early, so the addon is never added to proxiedAddons. Skip this client-side fetch when autoProxyDecision.shouldAutoProxy is true, or validate through the backend/proxy instead.

Proposed fix
-    try {
-      setLoading(true);
-      const response = await fetch(std);
-      if (!response.ok)
-        throw new Error(`${response.status} ${response.statusText}`);
-      await response.json();
-    } catch (error: any) {
-      toast.error(`Failed to fetch or parse manifest: ${error.message}`);
-      setLoading(false);
-      return;
-    }
+    setLoading(true);
+    if (!autoProxyDecision.shouldAutoProxy) {
+      try {
+        const response = await fetch(std);
+        if (!response.ok)
+          throw new Error(`${response.status} ${response.statusText}`);
+        await response.json();
+      } catch (error: any) {
+        toast.error(`Failed to fetch or parse manifest: ${error.message}`);
+        setLoading(false);
+        return;
+      }
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/frontend/src/components/menu/addons/_components/my-addons.tsx`
around lines 1015 - 1025, The fetch call to validate the manifest at line 1017
(within the try block fetching from `std`) needs to be skipped when
`autoProxyDecision.shouldAutoProxy` is true, since internal container URLs are
not reachable from the client browser. Add a conditional check before the fetch
statement to skip the client-side validation when auto-proxy is enabled,
allowing the backend/proxy to handle the validation instead after the proxy
configuration is applied at lines 1045-1051. This prevents early returns that
block the addon from being added to `proxiedAddons`.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/utils/http.ts`:
- Around line 299-312: The regex patterns checking for private IPv4 ranges
(127., 10., 192.168., 172.16-31., 169.254.) are matching any hostname that
starts with these strings, which incorrectly classifies DNS names like
10.example.com as private addresses. Parse and validate that the hostname is a
complete IPv4 literal (matching the full format of four dot-separated numeric
octets) before applying these private range checks. This ensures only actual
IPv4 addresses in private ranges are identified as internal, while DNS names
that happen to start with these patterns are not misclassified.

In `@packages/frontend/src/components/menu/addons/_components/my-addons.tsx`:
- Around line 1026-1051: The current implementation builds nextUserData from
userData that was captured before an asynchronous fetch operation, and then
ignores the setter's previous value when calling setUserData. This can overwrite
addon or proxy changes made while the fetch was pending. Move the entire block
of logic that finds currentPreset, builds baseNextUserData, applies
autoProxyDecision, and constructs nextUserData (lines 1026-1050) into a
functional update callback passed to setUserData. This ensures that the update
operates on the latest state at the time of the update rather than a stale
snapshot, preventing concurrent edits from being lost.
- Around line 36-39: The import statement for the proxy-auto module is missing
the required `.js` extension in the relative import path. Update the import
statement where the modules applyInternalAddonProxyConfig and
shouldAutoProxyInternalAddon are imported from './proxy-auto' to
'./proxy-auto.js' to comply with TypeScript NodeNext module resolution
requirements.

In `@packages/frontend/src/components/menu/addons/_components/proxy-auto.ts`:
- Around line 44-48: The regex patterns in the private IP range checks are
matching DNS hostnames that merely start with private range prefixes (like
10.example.com or 192.168.example.com) rather than actual private IP addresses.
Update each regex pattern in the conditions starting with /^(127\.)/, /^(10\.)/,
/^(192\.168\.)/, /^172\.(1[6-9]|2[0-9]|3[0-1])\./, and /^169\.254\./ to ensure
they match only complete IPv4 addresses in those private ranges, not arbitrary
hostnames with matching prefixes. This requires making the patterns stricter by
ensuring that after the prefix, only numeric octets and dots follow until the
end of the string, preventing false matches on DNS names.

---

Outside diff comments:
In `@packages/frontend/src/components/menu/addons/_components/my-addons.tsx`:
- Around line 1015-1025: The fetch call to validate the manifest at line 1017
(within the try block fetching from `std`) needs to be skipped when
`autoProxyDecision.shouldAutoProxy` is true, since internal container URLs are
not reachable from the client browser. Add a conditional check before the fetch
statement to skip the client-side validation when auto-proxy is enabled,
allowing the backend/proxy to handle the validation instead after the proxy
configuration is applied at lines 1045-1051. This prevents early returns that
block the addon from being added to `proxiedAddons`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 33a32cd3-87e7-4e6d-8c6d-4935b61f691d

📥 Commits

Reviewing files that changed from the base of the PR and between f0411bb and 0752166.

📒 Files selected for processing (6)
  • packages/core/src/main/resources.ts
  • packages/core/src/streams/proxifier.ts
  • packages/core/src/utils/http.ts
  • packages/frontend/src/components/menu/addons/_components/my-addons.tsx
  • packages/frontend/src/components/menu/addons/_components/proxy-auto.ts
  • packages/frontend/src/components/menu/addons/index.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/core/src/streams/proxifier.ts
  • packages/frontend/src/components/menu/addons/index.tsx
  • packages/core/src/main/resources.ts

Comment thread packages/core/src/utils/http.ts Outdated
Comment thread packages/frontend/src/components/menu/addons/_components/my-addons.tsx Outdated
Comment thread packages/frontend/src/components/menu/addons/_components/proxy-auto.ts Outdated
@IbbyLabs IbbyLabs marked this pull request as ready for review June 18, 2026 23:03

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/frontend/src/components/menu/addons/_components/my-addons.tsx`:
- Around line 1055-1059: The toast message in the autoProxyDecision conditional
is displaying a single generic message when it should differentiate between two
scenarios: whether the proxy was auto-enabled (credentials present) or
auto-targeted (requires credential configuration). Compute an autoEnabledProxy
boolean value before calling setUserData to determine which case applies, then
display different toast messages using toast.info based on this computed value
to match the messaging pattern used in index.tsx, ensuring users understand if
further proxy configuration is needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: bf4c1789-b26b-418f-9377-428d94620dee

📥 Commits

Reviewing files that changed from the base of the PR and between 0752166 and d71ab5a.

📒 Files selected for processing (3)
  • packages/core/src/utils/http.ts
  • packages/frontend/src/components/menu/addons/_components/my-addons.tsx
  • packages/frontend/src/components/menu/addons/_components/proxy-auto.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/core/src/utils/http.ts
  • packages/frontend/src/components/menu/addons/_components/proxy-auto.ts

@IbbyLabs

Copy link
Copy Markdown
Contributor Author

@Viren070 whenever you get a chance to look at this, I would appreciate your opinion

@IbbyLabs IbbyLabs force-pushed the feat/auto-proxy-http branch from f24414d to 31d2c90 Compare July 5, 2026 22:44
Auto-route addon stream and subtitle URLs whose host is an internal container hostname or private IP (e.g. http://nzbdav:8080) through the configured proxy, since an external player can't reach those. Also lets subtitle URLs be proxied on demand via the `subtitle` proxied-service, mirroring stream proxying.
@IbbyLabs IbbyLabs force-pushed the feat/auto-proxy-http branch from 31d2c90 to db49874 Compare July 5, 2026 23:04
@IbbyLabs IbbyLabs changed the title Auto-proxy internal addon endpoints (container hostnames) for streams and subtitles feat(proxy): auto-proxy internal addon endpoints and subtitle URLs Jul 5, 2026
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.

1 participant