Patch release: case-insensitive Cloudflare DNS record matching (#255),
Pushover URL parsing fix for canonical shoutrrr format (#258), and
Gotify URL parsing fix for ?token= query and ?disabletls=yes (#262).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Improve shoutrrr URL parsing for Gotify and Pushover
- Add parse_gotify_url to handle gotify://, gotify+http(s)://, token in
final path segment or ?token=, and ?disabletls=yes to force http
- Accept canonical pushover URLs by stripping an optional 'shoutrrr:'
user
prefix and ignoring query params
- Add tests for Gotify, Pushover, and Cloudflare parsing/lookup behavior
Switch reqwest to rustls-no-provider and add rustls crate; install
rustls provider at startup. Replace regex::Regex with regex_lite::Regex
across code. Consolidate api_get/post/put/delete into a single
api_request that takes a Method and optional body. Add .dockerignore and
UPX compression in Dockerfile. Remove unused domain/IDNA code, trim dead
helpers, tweak tokio flavor and release opt-level, and update tests to
use crate::test_client()
bump to 2.0.10
Legacy mode (config.json) never set the notify flag or generated
notification messages, so Shoutrrr services (Telegram, Discord, Slack,
etc.) were silently skipped even when DNS records were created or
updated. Propagate messages and the notify flag from the legacy update
path back to update_once() so notifications fire correctly.
The split client previously bound to 0.0.0.0 / [::] to force
IPv4/IPv6,
but this only hinted at the address family — happy-eyeballs could
still
race and connect over the wrong protocol on dual-stack hosts.
Introduce a FilteredResolver that strips wrong-family addresses from
DNS
results before the HTTP client sees them, matching the "split dialer"
pattern from favonia/cloudflare-ddns. This guarantees the client can
only
establish connections over the desired protocol.
Also switch Cloudflare trace URLs from literal resolver IPs
(1.0.0.1 / [2606:4700:4700::1001]) to cloudflare.com with an
api.cloudflare.com fallback — the DNS filter makes dual-stack
hostnames
safe, and literal IPs caused TLS SNI mismatches for some users.
- reqwest 0.12 → 0.13 (adds dns_resolver API)
- if-addrs 0.13 → 0.15
- tokio: add "net" feature for tokio::net::lookup_host
Deduplicate up-to-date messages by tracking noop keys and move logging
to the updater so callers only log the first noop.
Reuse a single reqwest Client for IP detection instead of rebuilding it
for each call.
Always ping heartbeat even when there are no meaningful changes.
Fix Pushover shoutrrr parsing (token@user order) and update tests
Introduce CachedCloudflareFilter that caches Cloudflare IP ranges and
refreshes every 24 hours. If a refresh fails the previously cached
ranges
are retained and a warning is emitted. Wire the cache through main and
updater so Cloudflare fetches reuse the cached result. Update tests and
bump crate version to 2.0.7
Use tokio::join to fetch IPv4 and IPv6 Cloudflare ranges in parallel.
When range fetch fails, avoid performing updates that could write
Cloudflare addresses by clearing detected/filtered IP lists and emitting
warnings. Add unit tests to validate parsing and boundary checks for the
current Cloudflare ranges. Bump crate version to 2.0.6.
Fetch Cloudflare ranges concurrently; avoid writes
Skip updates (clear detected IPs) if Cloudflare ranges can't be
retrieved to avoid writing Cloudflare anycast addresses.
Default REJECT_CLOUDFLARE_IPS=true, update README, add comprehensive
CF-range tests, and bump crate version
Fetch CF ranges concurrently and avoid updates
Enable rejecting Cloudflare IPs by default and skip any updates
if the published ranges cannot be fetched to avoid writing Cloudflare
anycast addresses. Fetch IPv4 and IPv6 ranges concurrently, add
parsing/matching tests, and update README and version.