183 Commits
Author SHA1 Message Date
NetworkCats 3298ba56eb Optimize MMDB response paths v1.0.3 v1.0.4 2026-05-25 18:55:23 +08:00
NetworkCats 6405e6aaa3 Fix IP validation and MMDB lookup handling 2026-05-25 18:40:51 +08:00
NetworkCatsandClaude Opus 4.7 4ba00fadf5 feat: poll MMDB every 6 hours to mitigate upstream release drift
The daily scheduled update at 01:20 UTC was systematically lagging the
upstream mergedipdb release by 24h. The upstream cron nominally fires
at 01:00 UTC but GitHub Actions schedule latency shifts the actual
publish time anywhere from ~01:05 to ~06:00+ UTC, so any fixed
single-daily time misses the current release on delayed days.

Introduce DB_UPDATE_INTERVAL_HOURS (default 6, must divide 24 evenly),
shift the anchor DB_UPDATE_TIME_UTC default to 00:20, and replace
secs_until_next with secs_until_next_tick that schedules at anchor +
N*interval. Also set RUST_LOG=rustyip=info,warn in the Ansible env
template so the scheduler and "database updated successfully (N bytes)"
info logs are actually visible in docker logs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v1.0.2
2026-04-22 07:26:57 +00:00
NetworkCatsandClaude Opus 4.7 a17b1053ff test: relax proxy classification assertions in integration tests
The /proxy, /hosting, /tor, /vpn endpoints and the /json response embed
live MMDB classifications for 45.77.77.77 that flip as the Merged-IP
dataset is updated. Replace hard-coded expected values with shape checks
(boolean / "true"|"false") so the tests verify endpoint plumbing without
coupling to transient upstream data.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v1.0.1
2026-04-21 07:38:56 +00:00
NetworkCatsandClaude Opus 4.7 794bed8690 test: remove brittle proxy classification assertion
The assertion that 45.77.77.77 is a Tor exit node depended on live MMDB
classifications that change as the Merged-IP dataset updates. The test
name promised "returns data for a known IP" — the remaining lookup_proxy
coverage already exercises the lookup path without pinning to transient
classifications.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 07:35:22 +00:00
NetworkCatsandClaude Opus 4.7 d1280a46ac feat: force fresh MMDB download on every deploy
Wipe the target color's database volume before starting the container so
each push re-downloads the latest Merged-IP.mmdb. Gate /health on DB
readiness (503 until loaded) so HAProxy blue-green only flips traffic
once the new backend has a usable DB, and raise the Ansible health-wait
window from 120s to 360s to cover the download.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 07:05:57 +00:00
NetworkCats 5e70e21296 fix: increase ssh-keyscan retries and wait for SSH port before scanning v1.0.0 2026-04-03 21:58:29 +08:00
NetworkCats afb5bd4c9b downgrade to Vultr Regular Performance 1vCPU/1GB and tighten resource limits
Switch from High Frequency 2vCPU/2GB ($18/mo) to Regular Performance
1vCPU/1GB ($5/mo). Tighten HAProxy rate limits from 100/50/30 RPM to
60/30/15 RPM with lower global RPS thresholds (200/300 instead of
300/500). Reduce maxconn, socket buffers, file descriptor limits, and
Docker resource settings to fit within 1GB RAM constraints. Update all
user-facing content and translations across 14 locales.
2026-04-03 21:18:09 +08:00
NetworkCats 22516e095f Update db.rs 2026-03-23 19:59:56 +08:00
NetworkCats bde6b91a74 fix: update proxy test assertions to match current MMDB data
45.77.77.77 no longer has is_proxy=true in the upstream database;
it now reports is_tor=true instead.
2026-03-23 19:45:56 +08:00
NetworkCats ab66dba48c fix: self-host Simple Line Icons and improve info table spacing
Replace the cdnjs CDN dependency with locally hosted font files and a
minimal CSS file containing only the 4 icons used (check, minus,
magnifier, social-github). Remove the CDN preconnect links.

Also reduce the gap between the IP display and the info table divider,
fix vertical alignment of icon and text rows by switching to
vertical-align: middle, and override the icon line-height to match
table text.
2026-03-23 19:33:55 +08:00
NetworkCats 0ee38b44df fix: ensure city label is available for JS-rendered alt IP rows
When the primary IP lacks city data, the conditional <tr data-label="city">
row is absent from the DOM, so readLabels() cannot scrape the translated
label. Embed translated labels as data-l-* attributes on the <table> element
so they are always available regardless of which rows are rendered.
2026-03-23 18:23:42 +08:00
NetworkCats c2247fc4a6 fix: add explicit line-height to ensure consistent layout across languages 2026-03-22 19:28:50 +08:00
NetworkCats ead6ee47be fix: reduce spacing between info table labels and values 2026-03-22 19:01:12 +08:00
NetworkCats c15d7ad36a fix: apply rustfmt and replace map_or with is_some_and per clippy 2026-03-22 18:23:22 +08:00
NetworkCats 991fd289a2 fix: improve accessibility to meet WCAG 2.2 AA/AAA standards
- Remove disruptive alert() on error pages, rely on role="alert" banner
- Add skip navigation link for keyboard users (WCAG 2.4.1)
- Fix heading hierarchy on error page (sr-only status text in h1)
- Add "opens in a new tab" screen reader hint on external links
- Wrap language selector in form with noscript submit button (WCAG 3.2.2)
- Add aria-label to copy-to-clipboard buttons and footer landmarks
- Use h2 for alt-IP section to maintain single h1 per page
- Add persistent underline on links for non-color identification (WCAG 1.4.1)
- Fix footer attribution contrast ratio to ~5.5:1 (WCAG 1.4.3)
- Add aria-busy/role=status loading announcements for skeleton state
- Add translations for new accessibility strings across all 14 locales
- Update integration tests to assert role="alert" instead of alert()
2026-03-22 18:21:29 +08:00
NetworkCats b76410abf4 modernize JS to ES2022+ module and fix CSS logical property consistency
Rewrite script.js from ES5 (IIFEs, var, .then() chains) to modern ES2022+:
const/let, arrow functions, template literals, async/await, optional
chaining, for...of, .includes(), AbortSignal.timeout(), and DOM APIs
for dynamic HTML construction. Fix unhandled clipboard rejection, abort
timeout leak, and global scope pollution. Update script tag to
type="module" and fix CSS: top -> inset-block-start, flex-start -> start,
and indentation in media query block.
2026-03-22 18:01:05 +08:00
NetworkCats 5af03bf9b9 fix: PO parser escape order, proxy endpoint consistency, and accessibility bugs 2026-03-22 17:52:25 +08:00
NetworkCats ab7fb7c3c6 refactor: migrate templates to Askama custom i18n filter syntax
Replace all {{ t_field_name }} template variables with {{ "msgid"|t(locale) }}
filter calls across all 6 template files. This works with the #[askama::filter_fn]
defined in handlers/html.rs, which calls i18n::translate() directly.

Templates updated: index.html, error_alert.html, error_page.html,
_footer.html, _footer_lang.html, _search_form.html
2026-03-22 17:33:55 +08:00
NetworkCats 8fba47afd1 refactor: split models.rs into mmdb/api sub-modules with pub(crate) visibility
Split the 865-line models.rs into 3 focused files:
- models/mod.rs: conversion logic, helpers, re-exports, tests
- models/mmdb.rs: MMDB deserialization types (internal, pub(crate))
- models/api.rs: API serialization types (public) with From<MmdbProxy> impl

Mmdb types are now pub(crate) since they are internal deserialization details
that should not be part of the public API surface.
2026-03-22 17:33:40 +08:00
NetworkCats ee6ec1a28b refactor: split handlers.rs into focused sub-modules with DRY improvements
Split the 957-line handlers.rs into 4 focused files:
- handlers/mod.rs: shared state, IP resolution, non-browser request helper
- handlers/html.rs: HTML template rendering with Askama custom i18n filter,
  eliminating the Translations struct and ~250 lines of boilerplate
- handlers/api.rs: JSON/plain-text API endpoints with generic field_handler
  and proxy_field_handler helpers (consolidates 8 near-identical handlers)
- handlers/seo.rs: robots.txt, sitemap, OpenAPI, manifest

DRY improvements included:
- extract_ip_from_header() parameterized helper (deduplicates CF/IPv4 extraction)
- handle_non_browser_request() helper (deduplicates CLI/JSON early-return)
- append_ip_query() helper (deduplicates ?ip= redirect construction)
- field_handler/proxy_field_handler generics (consolidates 8 handlers)
- Askama #[filter_fn] custom filter for i18n (eliminates Translations struct)
2026-03-22 17:33:26 +08:00
NetworkCats 77410593f2 refactor: consolidate DB lookup boilerplate, UA detection, and polish error/module docs
Phase 1 (DRY):
- db.rs: extract with_reader() helper to eliminate repeated load-guard-lookup
  boilerplate across 6 lookup functions; use From<MmdbProxy> for ProxyInfo
- ua_detect.rs: extract matches_any_prefix() shared by both prefix-matching fns

Phase 4 (Quality polish):
- error.rs: implement Debug, Display, and std::error::Error on AppError
- Add module-level //! docs to all source modules
2026-03-22 17:33:09 +08:00
NetworkCats ccfa7decda feat: schedule DB updates at fixed daily UTC time instead of interval
Replace DB_UPDATE_INTERVAL_HOURS with DB_UPDATE_TIME_UTC (HH:MM format,
default 01:20) so the database update runs at a predictable time each day.
This ensures the update happens 20 minutes after the upstream Merged IP
Data release at 01:00 UTC.
2026-03-22 16:43:02 +08:00
NetworkCats cefdceab2c feat: add dismissible noscript notification banner
Show a fixed bottom banner for users with JavaScript disabled,
using CSS checkbox hack for dismissal without requiring JS.
2026-03-22 16:30:30 +08:00
NetworkCats bf3d96ac9c fix: use semantic data-label keys for alt-IP table row labels
The JS used fragile numeric indices to look up localized labels from the
server-rendered table. When optional rows (ASN, Org, Country, City) were
missing for the primary IP, the indices shifted, causing 'Proxy' to appear
as the City label. Add data-label attributes to each <tr> in the template
and key the label map by name instead of position.
2026-03-22 16:23:14 +08:00
NetworkCats d078859c5c relax rate limits: 100/50/30 RPM tiers at 0/300/500 RPS thresholds 2026-03-22 14:13:12 +08:00
NetworkCats 4877724408 fix: dynamically scale down IPv6 address font size based on length 2026-03-22 12:34:26 +08:00
NetworkCats 66a3db8901 style: restore import order to satisfy cargo fmt 2026-03-22 12:20:27 +08:00
NetworkCats 41016891eb fix: update proxy test assertions to match current MMDB data
45.77.77.77 no longer has is_hosting=true in the upstream database;
it now reports is_anonymous=true instead.
2026-03-22 12:17:20 +08:00
NetworkCats da8434662f feat: add skeleton loading state for alt-IP section when primary IP is IPv6
Show a shimmer skeleton placeholder while fetching the local IPv4
address via the IPv4-only domain. When the primary IP is already IPv4,
no loading state is displayed and the alt section fades in directly.
2026-03-22 12:06:56 +08:00
NetworkCats d236302b09 fix: skip alt-IP detection when querying another IP address
The detectAltIp() function was unconditionally fetching the viewer's own
IPv6/IPv4 address and displaying it alongside queried IP results. Pass
the is_query flag to the client via a data attribute and guard the
alt-IP detection so it only runs when viewing your own IP.
2026-03-22 11:58:44 +08:00
NetworkCats fb661933e8 fix(deploy): replace SIGHUP reload with container recreate to fix bind mount staleness
Docker file-level bind mounts track inodes, not paths. Ansible template
writes create new inodes, leaving the container reading orphaned files.
Replacing SIGHUP with force-recreate ensures fresh mounts every time,
eliminating the admin socket dependency entirely.
2026-03-20 09:40:56 +08:00
NetworkCats bd71dae443 fix(deploy): preserve bind mount inode with unsafe_writes for HAProxy config 2026-03-20 08:56:06 +08:00
NetworkCats 09f3b6bd72 fix(deploy): move HAProxy admin socket to /tmp for correct permissions
The named Docker volume created /var/run/haproxy owned by root:root,
preventing the haproxy user (uid 99) from creating the socket file.
2026-03-20 08:17:36 +08:00
NetworkCats f72cf8190b fix(deploy): retry admin socket command after HAProxy reload 2026-03-20 07:36:52 +08:00
NetworkCats 1c8f274453 refactor(deploy): use HAProxy admin socket instead of stats HTTP API 2026-03-20 07:01:09 +08:00
NetworkCats 258f68af5d fix(deploy): force server out of maintenance after HAProxy SIGHUP reload 2026-03-20 06:49:29 +08:00
NetworkCats ec91cd7738 refactor: remove FAQPage JSON-LD structured data block 2026-03-20 06:20:50 +08:00
NetworkCats f2a6678bf5 Fix live demo link to use HTTPS
Updated the live demo link to use HTTPS.
2026-03-16 11:42:08 +08:00
NetworkCats c2fc9d00f4 fix(ci): disable codecov auto-search to prevent false file detection 2026-03-11 05:58:55 +08:00
NetworkCats 797bb7c76a fix Fmt 2026-03-10 21:44:29 +00:00
NetworkCats 60e4f08fd3 docs: update installation guides for IPv4 domain configuration 2026-03-11 05:06:58 +08:00
NetworkCats d7f24cc0ab feat: update Ansible and deploy workflow for IPv4 domain support 2026-03-11 05:03:43 +08:00
NetworkCats 3f11d2161f fix: use localized names in JS-rendered secondary IP info table 2026-03-11 04:43:12 +08:00
NetworkCats bcb06e0e82 test: add integration tests for IPv4 domain routing and dual-stack detection 2026-03-11 04:41:41 +08:00
NetworkCats 1872142bbb feat: add JS dual-stack IP detection with full info display 2026-03-11 04:40:05 +08:00
NetworkCats 8567630f7a feat: add host-based routing and IPv4 domain handler with CORS 2026-03-11 04:38:10 +08:00
NetworkCats dfdfda0e81 feat: add HAProxy dual-domain routing with separate IPv4 headers 2026-03-11 04:33:47 +08:00
NetworkCats c876d17e8c feat: add IPV4_DOMAIN config for dual-stack IP detection 2026-03-11 04:33:01 +08:00
NetworkCats 5565f4a0a5 feat: add HTTP port 80 support with Cloudflare-only firewall rules 2026-03-08 05:52:42 +08:00