Commit Graph
18 Commits
Author SHA1 Message Date
clawbot 6ce4ee255b Answer HEAD requests and give 405 a plain message (closes #111)
check / check (push) Canceled after 0s
Every route was registered for GET only, so HEAD answered 405, and on
the JSON routes that 405 said "Internal server error". chi's GetHead
now serves HEAD with the GET handler. The /api/v1 and /ip route groups
answer a path they lack with a JSON 404 "Not found", and the other
methods the router knows (POST, PUT, PATCH, DELETE, OPTIONS, TRACE,
CONNECT) with a JSON 405 "Method not allowed" whose Allow header names
GET and HEAD. JSONValidationMiddleware gives a 4xx sent without a JSON
body the status's standard text instead of "Internal server error".

Model: opus-5-5
2026-10-20 00:41:34 +00:00
clawbot 89bdda18a5 Add the HTTP hardening the policy requires before 1.0 (closes #108)
check / check (push) Canceled after 0s
Every answer carries the six security headers REPO_POLICIES.md lists.
The Content-Security-Policy allows inline content only with a nonce made
for that answer; the pages put it on their style and script blocks and
drop their four style attributes.

The request log and /ip/ take a forwarded address only from a proxy
listed in TRUSTED_PROXIES, which stops the start when set but invalid:
the last X-Forwarded-For entry that is not a trusted proxy. X-Real-IP
and True-Client-IP are no longer read.

The JSON routes and the health check send fixed messages in place of
database, parser and resolver errors, and log the detail.

Model: opus-5-5
2026-10-20 01:36:18 +02:00
clawbot d2a6e30360 Percent-decode URL parameters before parsing them (closes #103)
check / check (push) Canceled after 0s
chi matches routes against the escaped path when a request has one and
hands the handlers their URL parameters still percent-encoded. The home
page's lookup form encodes the address it asks for, so every IPv6 lookup
answered 400, as did a comma-separated address list or a prefix that a
client percent-encoded. The router now matches against the decoded path,
so every handler reads its parameters decoded.

Model: opus-5-5
2026-10-19 23:02:00 +02:00
clawbot b89987e356 Re-vendor the shared files from sneak/prompts at 0653579 (closes #52)
check / check (push) Canceled after 0s
Takes .golangci.yml, .dockerignore, .gitignore, .editorconfig, the
workflow and REPO_POLICIES.md from sneak/prompts 0653579, with this
repository's own entries after the shared content. Lint (golangci-lint
v2.14.0) and test are Dockerfile phases that script/lint and script/test
build alone with a new CACHEBUST value, keeping Go's and golangci-lint's
caches; the image build depends on both. make fmt and make fmt-check also
format the markdown with prettier, pinned in yarn.lock. The agent
guidance moves to AGENTS.md. The Go code is fixed for what the new
configuration finds, and the AS and prefix detail reads now return the
rows' error after their loops.

Model: opus-5-5
2026-10-19 12:10:11 +02:00
clawbot ae6d885a5a Answer 504, not 408, when a request outlasts its time limit (closes #70)
check / check (push) Canceled after 0s
A request past the server's 30-second limit answered 408, which tells the
client it was too slow sending its request, and /api/v1/stats answered 500
when its 4-second read ran out. The limit is now chi's middleware.Timeout,
which answers 504 and never writes from a second goroutine while the
handler is writing.

Right after each database read or host name lookup, whatever came back, a
handler asks deadlinePassed whether its time limit has passed and, if so,
answers 504, with the JSON error body on JSON routes: a cut-off read can
return part of its rows without an error. The health check is unchanged.

Model: opus-5-5
2026-10-19 10:02:23 +02:00
sneak a163449a28 Improve request logging and make health check lightweight
- Log slow requests (>1s) at WARNING level with slow=true flag
- Log request timeouts at WARNING level in TimeoutMiddleware
- Replace heavy GetStatsContext with lightweight Ping in health check
- Add Ping method to database interface (SELECT 1)
2026-01-01 06:06:20 -08:00
sneak 4284e923a6 Add navbar and home page with search functionality
- Create new home page (/) with overview stats, ASN lookup,
  AS name search, and IP address lookup with JSON display
- Add responsive navbar to all pages with app branding
- Navbar shows "routewatch by @sneak" with link to author
- Status page accessible via navbar link
- Remove redirect from / to /status, serve home page instead
2025-12-31 14:56:02 -08:00
sneak 45810e3fc8 Fix prefix URL routing for encoded CIDR notation
Change route from wildcard /prefix/* to explicit /prefix/{prefix}/{len}
to properly handle URL-encoded IPv6 addresses with CIDR notation.

- Separate prefix and length into individual path parameters
- Add prefixURL template function for generating correct links
- Remove url.QueryUnescape from handlers (chi handles decoding)
2026-01-01 05:37:37 +07:00
sneak 1115954827 Fix prefix URL routing to handle CIDR notation with slashes
- Use wildcard route pattern for /prefix/* endpoints
- Extract prefix parameter using chi.URLParam(r, "*")
- Fixes 400 error when accessing /prefix/x.x.x.x/32 directly
2025-12-30 14:41:57 +07:00
sneak 3a9ec98d5c Add structured HTTP request logging and increase timeouts
- Replace chi's Logger middleware with structured slog-based logging
- Log request start (debug) and completion (info/warn/error by status)
- Include method, path, status, duration_ms, remote_addr in logs
- Increase request timeout from 8s to 30s for slow queries
- Add read/write/idle timeouts to HTTP server config
- Better server startup logging to confirm listening state
2025-12-30 13:37:54 +07:00
sneak da6d605e4d Add production hardening: health check, streamer panic fix, db maintenance
- Add health check endpoint at /.well-known/healthcheck.json that
  verifies database and RIS Live connectivity, returns 200/503

- Fix panic in streamer when encountering unknown RIS message types
  by logging a warning and continuing instead of crashing

- Add DBMaintainer for periodic database maintenance:
  - VACUUM every 6 hours to reclaim space
  - ANALYZE every hour to update query statistics
  - Graceful shutdown support

- Add Vacuum() and Analyze() methods to database interface
2025-12-29 15:55:54 +07:00
sneak 3b159454eb Add IP information API with background WHOIS fetcher
- Add /ip and /ip/{addr} JSON endpoints returning comprehensive IP info
- Include ASN, netblock, country code, org name, abuse contact, RIR data
- Extend ASN schema with WHOIS fields (country, org, abuse contact, etc)
- Create background WHOIS fetcher for rate-limited ASN info updates
- Store raw WHOIS responses for debugging and data preservation
- Queue on-demand WHOIS lookups when stale data is requested
- Refactor handleIPInfo to serve all IP endpoints consistently
2025-12-27 15:47:35 +07:00
sneak 2f96141e48 Fix IPv6 prefix length links to use separate /prefixlength6/<len> route
The prefix length links for IPv6 prefixes were incorrectly pointing to
/prefixlength/<len> which would show IPv4 prefixes. Added a new route
/prefixlength6/<len> specifically for IPv6 prefixes and updated the
template to use the correct URL based on whether displaying IPv4 or IPv6
prefix distributions.

Also refactored handlePrefixLength to explicitly handle only IPv4 prefixes
and created handlePrefixLength6 for IPv6 prefixes, removing the ambiguous
auto-detection based on mask length value.
2025-08-09 11:37:14 +02:00
sneak 1fded42651 Quadruple all HTTP timeouts to prevent timeout errors
- HTTP request timeout: 2s -> 8s
- Stats collection context timeout: 1s -> 4s
- HTTP read header timeout: 10s -> 40s

This should prevent timeout errors when the database is under load
or when complex queries take longer than expected (slow query
threshold is 50ms).
2025-07-29 04:18:07 +02:00
sneak 3338e92785 Add JSON validation middleware to ensure valid API responses
- Created JSONValidationMiddleware that validates all JSON responses
- Ensures that even on timeout or internal errors, a valid JSON error response is returned
- Applied to all API endpoints including /status.json
- Prevents client-side JSON parse errors when server encounters issues
2025-07-29 04:13:01 +02:00
sneak ba13c76c53 Fix prefix distribution bug and add prefix length pages
- Fix GetPrefixDistribution to count unique prefixes using COUNT(DISTINCT prefix) instead of COUNT(*)
- Add /prefixlength/<length> route showing random sample of 500 prefixes
- Make prefix counts on status page clickable links to prefix length pages
- Add GetRandomPrefixesByLength database method
- Create prefix_length.html template with sortable table
- Show prefix age and origin AS with descriptions
2025-07-28 18:42:38 +02:00
sneak af9ff258b1 Add /ip/<ip> route that redirects to prefix detail page
- Implement handleIPRedirect handler that looks up the prefix containing an IP
- Add /ip/{ip} route to routes.go
- Reuse existing GetASInfoForIP database method which returns prefix info
- Redirect to /prefix/<prefix> page with HTTP 303 See Other status
- Handle invalid IPs (400) and IPs with no route (404)
2025-07-28 04:31:22 +02:00
sneak 27ae80ea2e Refactor server package: split handlers and routes into separate files
- Move all handler functions to handlers.go
- Move setupRoutes to routes.go
- Clean up server.go to only contain core server logic
- Add missing GetASDetails and GetPrefixDetails to mockStore for tests
- Fix linter errors (magic numbers, unused parameters, blank lines)
2025-07-28 04:00:12 +02:00