14 KiB
Changelog
All notable changes to goget are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
1.1.0 — 2026-06-30
Added
Documentation
- Standalone troff manpage —
man/goget.1is now the single source of truth for the goget(1) manual. The previous embedded manpage listed only ~30 of the 138 CLI flags and was missing every standard section; the new file documents every flag with a dedicated entry, the full set of conventional.SHsections (NAME, SYNOPSIS, DESCRIPTION, OPTIONS, EXAMPLES, EXIT STATUS, FILES, ENVIRONMENT, SEE ALSO, HISTORY, AUTHORS, REPORTING BUGS, COPYRIGHT), curl/wget compatibility notes, and a release-history entry. The manpage is embedded into the binary via//go:embed, so--generate-man-pageandman gogetnow agree. just man— new task that runsgroff -man -ww -Kutf-8 -zoverman/goget.1to validate the troff source. Skips cleanly whengroffis not installed (CI on minimal images still passes).just install-manandjust uninstall-man— install the manpage to$HOME/.local/share/man/man1/goget.1.gz(XDG rootless, gzipped, reinstall-safe). Afterjust install-man,man gogetresolves the page automatically via the user'sMANPATH.
Core engine
- Unified worker pool — single protocol-agnostic worker pool (
internal/pool) used by FTP, SFTP, and WebDAV recursive-parallel downloads. Replaces three near-identical semaphore+WaitGroup implementations with a shared, tested concurrency primitive. - Graceful shutdown on SIGINT — persist
.goget.metasidecar on interrupt for SFTP single-file downloads, ensuring progress is saved for resume. - Gemini resume & metadata — Gemini downloads now persist
.goget.metasidecar on interrupt and delete it on successful completion.--resumecontinues interrupted Gemini transfers from the saved byte offset. - Gopher resume & metadata — Gopher
typeHTMLandtypeTextFileresponses now persist.goget.metasidecar on interrupt and delete it on successful completion.--resumecontinues interrupted Gopher text transfers, skipping already-written output bytes (post-transform length because Gopher line metadata is stripped before writing).
Security
- Certificate pinning across all TLS protocols —
--pinned-certnow applies to FTPS, Gemini, and WebDAVS in addition to HTTP/HTTPS. The leaf certificate SHA-256 hash is verified viatls.Config.VerifyPeerCertificateon every TLS-bearing protocol. - SSH host-key pinning for SFTP — new
--pinned-host-keyflag pins the SSH host key by its OpenSSH fingerprint (SHA256:<base64>, as produced byssh-keygen -lf). Raw lowercase-hex SHA-256 of the key wire format is also accepted. Pinning takes precedence over--ssh-insecureandknown_hosts. - WebDAV TLS config fix —
webdav.Protocol.getHTTPTransportnow builds itstls.Configfrom the caller-providedtransport.TLSConfiginstead of a fresh config that silently dropped CA certs, mTLS, keylog, and pinned-cert settings.
Recursive downloading & mirroring
--adjust-extensionextended to non-HTTP protocols — applies.htmlextension totext/htmlfiles downloaded via Gopher and WebDAV.--backup-converted— keep.origbackups of files before link conversion during recursive mirroring. Previously only available for HTTP/HTTPS; now works for WebDAV mirrors too.
Download management
--show-metadata— displays.goget.metasidecar contents for debugging interrupted / resumed downloads. Accepts a path to the downloaded output (the sidecar is located next to it) or a direct path to the sidecar file. Renders a human-readable summary by default and switches to raw JSON output when combined with--json. Credentials embedded in the stored URL are masked before display (the password placeholder isxxxxx).
Fixed
-
Gopher:
ctx.Done()cancellation goroutine leak — the goroutine spawned inDownloadto close the socket onctx.Done()previously waited indefinitely on the parent context, leaking every time the context outlived the function. Now bounded by adefer-closeddonechannel so the goroutine exits on every return path. -
Gemini:
ctx.Done()cancellation goroutine leak — same bug, same fix indownloadWithRedirects. -
Gopher: partial state lost on cancel-then-close — when the server closed the connection after
ctxwas cancelled,downloadTexttreated the resulting EOF as a successful end-of-stream and never persisted.goget.meta. Mirrors the equivalent Gemini behavior (already present from the Gemini resume feature): ifctx.Err() != nil, save partial state and return the context error. -
Gopher:
--resumeignored when caller suppliesWriter— when--resumewas set together with a caller-suppliedWriter, the partial-state sidecar would track bytes that landed in theWriterrather thanOutput.--resumeis now silently disabled in that case (with a--verbosewarning), keeping metadata consistent with the actual on-disk state. -
Gemini:
--resumeignored when caller suppliesWriter— same fix applied todownloadWithRedirects.
Testing
cmd/goget/man_page_test.go— new test file. Asserts the embedded manpage is non-empty, carries a.TH GOGET 1header, contains every mandatory.SHsection, and documents every flag registered bydefineFlags(so adding a new flag without documenting it now breaks the build). Whengroffis installed, also runsgroff -man -ww -Kutf-8 -zover the embedded source and fails on any warning.- Resume tests deterministic across the protocol stack
(
TestGeminiResume{SaveMetadata,Download}andTestGopherResume{SaveMetadata,Download}) — the four tests previously relied on a fixedtime.Sleepbefore callingcancel(), making them flaky on slow CI schedulers. They now wait for aProgressCallbacksignal, which fires synchronously after the firstwriter.Writelands on disk. - Goroutine leak regression suite
(
TestGeminiCancelGoroutineExits,TestGopherCancelGoroutineExits) — runs 50 downloads back-to-back, settles the runtime viaruntime.GC(), and assertsruntime.NumGoroutine()returns to baseline + 1 within a 2-second window. TestGopherResumeInformation— new regression test covering thetypeInformationtext-mode path through resume, which differs fromtypeHTML/typeTextFilebecause lines are passed through verbatim (no metadata strip).TestGopherResumeStaleMetadatanow asserts that an orphan.goget.metacarried over from a different URL is deleted once a successful fresh download completes, preventing it from being picked up by a future--resumerun.
1.0.0 — 2026-06-26
First public release: a modern IPv6-first command-line download utility built on the Go standard library. goget provides parallel chunked downloads, resume support, checksum verification, recursive website mirroring, and support for 9 network protocols — all in a single static binary with zero runtime dependencies.
Added
Core engine
- Unified download and upload architecture via
core.Protocolinterface. - Protocol registry with scheme normalization (https→http, ftps→ftp).
- Structured error types (
NETWORK,PROTOCOL,FILE,TIMEOUT,AUTH,CHECKSUM,UNSUPPORTED,CANCELLED). - Request context with protocol chain tracking, attempt counting, and cancellation.
- Smart timeout calculation based on file size, minimum speed, and safety factor.
- IPv6-first transport dialer with automatic IPv4 fallback.
Protocols
- HTTP/HTTPS — HTTP/1.1 and HTTP/2, TLS 1.2/1.3, content negotiation, auto-decompression.
- FTP/FTPS — active and passive modes, explicit TLS (AUTH TLS), resume via REST command.
- SFTP — custom SFTP v3 implementation over SSH,
known_hostsverification, resume, private key and password authentication. - WebDAV — file download, recursive directory download, upload via HTTP PUT, MKCOL for directory creation.
- file:// — local file copy with recursive directory support.
- data: — RFC 2397 data URIs (base64 and plain text).
- Gopher — RFC 1436 with item type parsing.
- Gemini — TLS 1.2+ connections, redirect following, status code handling (1x–6x).
Network & transport
- Concurrent chunked downloads for files over 100 MB with
Rangerequests. - Per-chunk resume metadata for interrupted parallel downloads.
- HTTP CONNECT and SOCKS5 (
socks5://,socks5h://) proxy support with username/password authentication. - Custom DNS servers via
--dns-servers. - Network interface binding via
SO_BINDTODEVICE(Linux). - SSRF protection — blocks connections to private/internal IPs by default,
override with
--allow-private. - IPv4-mapped IPv6 normalization to prevent SSRF bypass.
- Token bucket rate limiting.
- Exponential backoff retry logic with configurable max retries.
--retry-all-errorsto retry on HTTP 4xx/5xx responses.--pinned-certSHA-256 certificate pinning.
Authentication
- HTTP Basic authentication (RFC 7617).
- HTTP Digest authentication (RFC 7616).
- OAuth 2.0 — client credentials, authorization code, password, and refresh token grant types with 30-second expiry grace period.
- OAuth error sanitization (RFC 6749 §5.2).
.netrcauto-reading with machine and default entry resolution.- Netscape-format cookie jar with import/export.
- Per-request cookies via
--cookieCLI flag. - SFTP SSH key auto-detection.
--password-filefor secure password loading.- Config sanitization — strips credentials when saving to disk.
core.SafeURL()— strips credentials from URLs in error messages and logs.
Recursive downloading & mirroring
- Recursive HTML link following with configurable depth limit.
- Full website mirroring with infinite depth and automatic link conversion.
- HTML parsing via
golang.org/x/net/html. - Link filtering by domain, accept pattern (glob and MIME), reject pattern, and exclusion list.
- Page requisites — automatic CSS, JavaScript, and image downloading.
--no-parent,--span-hosts,--domains,--random-wait.--adjust-extension,--timestamping,--cut-dirs.- Link rewriting for offline viewing — absolute, protocol-relative, and root-relative URLs.
--backup-convertedkeeps.origbackups before link conversion.robots.txtcompliance with--no-robotsoverride.
Verification & security
- Checksum verification — SHA-256, SHA-512, SHA3-256, SHA3-512, BLAKE2b, MD5.
- SHA256SUMS file parsing (plain and binary-mode).
- PGP detached signature verification (
.asc,.sig,.gpg). - PGP decryption with private key and passphrase.
- HSTS cache (RFC 6797) — automatic HTTP→HTTPS upgrade.
- TLS certificate pinning, mTLS support, custom CA bundle.
--ssl-key-logTLS session key logging (Wireshark-compatible).- Atomic file writes with mode
0600for config, resume metadata, and temp files.
Download management
- Persistent download queue with priority (1–10) and JSON storage.
- Multi-source Metalink downloads (
.meta4,.metalink) with automatic failover. - Batch URL loading from files.
- Cron-based scheduling (
MIN HOUR DOM MON DOWandYYYY-MM-DD HH:MM). - Post-download command hooks with environment variables.
- WARC (Web ARChive) output for archival compliance.
- Upload support — HTTP PUT and POST with multipart form data.
Output & progress
- Unicode progress bar with filled/empty blocks and real-time speed.
- Speed sparkline — mini ASCII chart of recent speed history.
- Estimated time remaining (ETA) calculation.
- Dot progress bar style, JSON progress output for scripting.
--write-outmetadata output,--trace-timeHTTP timing breakdown.--show-headers,--keep-timestamps,--content-disposition.- Color output with
always,never, andautomodes (honorsNO_COLOR).
Archive & compression
- Transparent decompression — gzip, deflate, zlib, bzip2, LZW.
- Archive extraction — TAR, TAR.GZ, TAR.BZ2, ZIP with auto-detection.
Internationalization
- IDN (International Domain Names) support with Punycode conversion via
golang.org/x/net/idna.
CLI
- Long flags only (
--url,--output,--verbose). - Shell completion generation — bash, zsh, and fish.
- Man page generation in troff format.
- Category-organized help text.
--info,--benchmark,--spider,--dry-run,--glob.
Configuration
- TOML configuration file at
~/.config/goget/config.toml. GOGET_CONFIGenvironment variable for alternative config path.- CLI flag overrides merged on top of config and defaults.
- Config commands — init, get, set, list, unset.
Library API (pkg/api/)
Clienttype with functional options (WithTimeout,WithUserAgent,WithVerbose).Client.Download()andClient.Upload()with structured request/result types.QueueClientfor programmatic queue management.ParseMetalink(),FetchMetalink(),LoadConfig(),DefaultConfig(),ParseSpeed(),Version().- One-shot convenience functions:
Download(),Upload().
Build & platforms
- Linux — amd64, arm64, riscv64, loong64.
- FreeBSD — amd64, arm64, riscv64.
- Static binary with zero runtime dependencies (stdlib only +
golang.org/x/packages). - Race detector enabled in tests, fuzz tests for security-critical parsers.
- Coverage gate at 40%.
Project & tooling
- Documentation set: architecture, API, authentication, CLI reference, configuration, download pipeline, protocols, recursive & mirror, security.
justtask set (install,run,build,test,uninstall).- Forgejo Actions CI (go vet, test + race, fuzz, release).
CONTRIBUTING.mdwith Conventional Commits and release process.