Skip to content

feat(config): add HTTP/HTTPS proxy config for outbound NZB traffic#606

Merged
javi11 merged 1 commit into
mainfrom
session/brave-kirch-4dd779
May 22, 2026
Merged

feat(config): add HTTP/HTTPS proxy config for outbound NZB traffic#606
javi11 merged 1 commit into
mainfrom
session/brave-kirch-4dd779

Conversation

@javi11
Copy link
Copy Markdown
Owner

@javi11 javi11 commented May 22, 2026

Summary

Adds a top-level network config block (http_proxy, https_proxy, no_proxy) exposed via the UI and applied to every outbound HTTP client used for grabbing NZBs and talking to indexers / arrs. Internal endpoints (RC server, self-loopback) are unaffected.

Closes the gap in #593 — env-var-only proxy routing is too coarse, leaks into internal calls, and is hard to manage in Docker / Gluetun stacks where indexers enforce IP consistency between search and grab.

What changed

Backend

  • New NetworkConfig struct (http_proxy / https_proxy / no_proxy) on config.Config with yaml/mapstructure/json tags. Defaults to empty (no proxy).
  • New internal/httpclient/proxy.go + factory.go: WithProxyConfig(...) option and NewForExternal(net, timeout) helper. Backed by golang.org/x/net/http/httpproxy so semantics match HTTP_PROXY / HTTPS_PROXY / NO_PROXY env vars but the config is authoritative (env is not consulted).
  • Constructors updated to accept *http.Client:
    • prowlarr.NewClient (Stremio addon search + NZB download)
    • sabnzbd.NewSABnzbdClient (fallback host)
    • nzblnk.NewResolver (NZBKing / NZBIndex)
    • arrs/clients.NewManagerstarr.Config.Client injected for every Radarr / Sonarr / Lidarr / Readarr / Whisparr instance.
  • API: "network" added to the PATCH switch in config_handlers.go. GET serializes through the embedded *config.Config, no extra response struct needed (no secrets to mask).

Frontend

  • NetworkConfig TS interface + ConfigResponse.network + ConfigUpdateRequest.network.
  • New NetworkConfigSection.tsx under the System group with three inputs and a DaisyUI info alert describing scope and the hot-reload caveat.

Tests

  • 6 new httpclient unit tests covering: all-empty, HTTP-only, HTTPS-only, NO_PROXY match, transport application, and empty disables.
  • 2 new config tests covering yaml round-trip and default-empty behaviour.

Known limitations

  • Per-call clients (Stremio addon, NZBLNK resolver, SABnzbd fallback) read cfg.Network on every request — proxy changes apply on the next outbound call.
  • Long-lived clients (arrs clients.Manager, importer sabnzbdClient) are constructed once at startup. The UI alert tells the user to restart AltMount to apply new proxy settings to those. Wiring config.OnConfigChange to rebind is a follow-up.

Test plan

  • go build ./... clean
  • go vet ./... clean
  • go test ./internal/httpclient/... ./internal/config/... -race — all pass
  • bun run build (frontend) — production bundle generated
  • Manual: set http_proxy/https_proxy via UI, point at a local Squid / tinyproxy, trigger a Stremio search + arrs queue check + nzblnk grab + SABnzbd fallback, confirm requests appear in the proxy log
  • Manual: add an indexer host to no_proxy, confirm bypass
  • Manual: confirm internal calls (/api/config, RC server) do not route through the proxy

Adds a top-level `network` config block (http_proxy / https_proxy /
no_proxy) exposed via the UI and applied to every outbound HTTP client
used for indexer search, NZB grabbing, Arrs (Radarr/Sonarr/Lidarr/
Readarr/Whisparr), SABnzbd fallback, and the NZBLNK resolver. Internal
endpoints (RC server, self-loopback) keep direct connections.

Replaces reliance on process-wide HTTP_PROXY / HTTPS_PROXY env vars,
which leak into internal calls and are awkward to manage in Docker /
Gluetun setups. Required by users (e.g. NZBHydra2 + indexers) that
enforce IP consistency between search and grab.

Implementation:
- NetworkConfig struct + getters in internal/config/manager.go.
- httpclient.WithProxyConfig + NewForExternal helpers in
  internal/httpclient (proxy.go, factory.go) backed by
  golang.org/x/net/http/httpproxy. No env-var consultation; config is
  authoritative.
- Constructors for prowlarr.NewClient, sabnzbd.NewSABnzbdClient,
  nzblnk.NewResolver, and arrs/clients.NewManager now accept an
  *http.Client so proxy + timeout settings flow through. starr.Config
  Client field is injected for every arr.
- API: "network" added to PATCH switch; GET serializes via embedded
  *config.Config.
- Frontend: NetworkConfig type + NetworkConfigSection.tsx registered
  in the System group of ConfigurationPage.tsx.
- Tests: proxy/no_proxy/empty unit tests plus a yaml round-trip test.

Refs #593.
@javi11 javi11 merged commit 646ffa9 into main May 22, 2026
2 checks passed
@javi11 javi11 deleted the session/brave-kirch-4dd779 branch May 22, 2026 06:56
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