<feed xmlns='http://www.w3.org/2005/Atom'>
<title>skunky-art.git/app/httpclient.go, branch main</title>
<subtitle>alternative deviantart frontend, no javascript. go.
</subtitle>
<id>http://git.krz.sh/krz/skunky-art.git/atom?h=main</id>
<link rel='self' href='http://git.krz.sh/krz/skunky-art.git/atom?h=main'/>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/skunky-art.git/'/>
<updated>2026-07-15T07:24:58+00:00</updated>
<entry>
<title>fix: harden HTTP transport, server timeouts and panic paths</title>
<updated>2026-07-15T07:24:58+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-15T07:24:58+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/skunky-art.git/commit/?id=7eb5e5e2230b6fb5b1bed6f0eaa03279aa61555b'/>
<id>urn:sha1:7eb5e5e2230b6fb5b1bed6f0eaa03279aa61555b</id>
<content type='text'>
Correctness and security findings surfaced by golangci-lint, plus two
latent panics found alongside them.

- router: http.ListenAndServe has no timeouts at all (gosec G114), so a
  slow client could hold a connection and its handler open indefinitely.
  Replace it with an explicit http.Server carrying read/write/idle
  timeouts.
- httpclient: InstallDAThrottle asserted http.DefaultTransport was a
  *http.Transport and would panic outright if anything had already
  wrapped it -- which is precisely what that function does. Check the
  assertion and fall back to a fresh transport. Expose ProxiedTransport
  so a configured download-proxy can inherit the same throttle and
  timeouts instead of silently bypassing them.
- cache: the Sys() assertion to *syscall.Stat_t is only valid on unix and
  would panic elsewhere; skip rotation instead. Indexing
  Headers["Content-Type"][0] panics when the header is absent; use
  Headers.Get. Cache files are written 0600 rather than 0700, as they are
  never executed.
- cli, api: check error returns, and exit rather than nil-dereference a
  file handle that failed to open.

SHA-1 and math/rand keep //nolint:gosec with reasons: they are cache-key
hashes and random-artwork picks, not security primitives.
</content>
</entry>
<entry>
<title>feat: throttle and time out outbound DeviantArt requests</title>
<updated>2026-07-15T01:22:26+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-07-15T01:22:26+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/krz/skunky-art.git/commit/?id=5763dc3cfeadf491d6eda3b6a91623f86396a134'/>
<id>urn:sha1:5763dc3cfeadf491d6eda3b6a91623f86396a134</id>
<content type='text'>
DeviantArt fronts its API with CloudFront + WAF, which bans egress IPs
that hit it too hard. devianter issues requests with a bare http.Client,
so unbounded concurrent handlers each pulled ~150-200 KB of JSON, which
both risked a ban and could exhaust the process under a bot flood.

Wrap the default transport to bound rate and concurrency for
deviantart.com and add timeouts. Other hosts (wixmp image CDN) pass
straight through, so media stays fast, and ProxyFromEnvironment is
preserved so HTTPS_PROXY egress still works.
</content>
</entry>
</feed>
