6.5 KiB
curl / wget CLI parity (Bare OS booter)
HTTP in Pear/Bare uses WHATWG Fetch (Node fetch or bare-fetch on bare-http1 / bare-https), not libcurl or GNU wget (C). The lists below track how close the booter shims are to common CLI flags.
History: -O / -o mutual exclusion, -I -L with manual redirects and %{num_redirects}, and wget -c (Range / 206 / 416) landed in a7e08e09. Later work added cookie jar, -J, --connect-timeout, **--cacert / -k**, BARE_OS_DNS_ALLOWLIST, Pear-safe fetch bootstrap (bare-os-ensure-bare-fetch.js), and wget --no-clobber.
curl (lib/curl-cli.js)
- URL interleaving, scheme guess (
http://,https:for//) — supported —http-fetch-url.js -X/--request— supported-H/--header— supported-A/--user-agent— supported — DefaultDEFAULT_CURL_USER_AGENT; last-Aor-HUser-Agent wins-d,--data*,--json— supported-o/--output— supported — VFS path; multiple URLs →FILE.N-O/--remote-name— supported — Saves using URL basename (like curl)-T/--upload-file— supported — PUT-I/--head— supported-i/--include— supported-L/--location— supported —-I -Luses HEAD then GET after redirect (curl semantics); plain GET usesredirect: follow-f/--fail— supported — Exit 22-s/-S/-v— supported-u/--user— supported — Basic auth only-m/--max-time— supported — Whole-requestAbortSignaltimeout; combined with--connect-timeoutasmin(max-time, connect-timeout)when both are set-w/--write-out— partial —%{http_code},%{url_effective},%{size_download};%{num_redirects}non-zero only for-I -Lmanual hop path-V/--version,-h/--help— supported- Cookie jar,
--cookie,-b,-c/--cookie-jar— supported — JSON maphostname → { name → value }on~/.config/bare-os/curl/cookies.json(or path from-c);-bfile orname=value; seecurl-cli.js --connect-timeout— supported — Seconds (integer or decimal); sets the abort deadline when used alone, orminwith--max-timewhen both are set.**-Y/-y** remain out of scope--cacert,-k/--insecure— supported — Globalfetch: Node undiciAgent. Whenctx.httpFetchis set, TLS intent is passed asinit.bareOsCurlTls(insecure, optionalcaPem, optionalpinnedSha256fromBARE_OS_TLS_PIN_SHA256) for the host implementation- TLS client certs (mutual TLS) — out of scope — Stack only
- HTTP/2, HTTP/3, SOCKS, FTP, SCP — out of scope
-Jcontent-disposition filename — supported — With-O; usesContent-Dispositionbasename only; rejects..and absolute paths in the server-provided name
wget (lib/wget-cli.js)
- URL interleaving, short clusters (
-qO-,-T30) — supported -O/--output-document— supported —-= stdout; one URL only with-O-P/--directory-prefix— supported — Cannot combine with-O-q/--quiet— supported-U/--user-agent— supported — DefaultDEFAULT_WGET_USER_AGENT-T/--timeout— supported — Same semantics as curl--max-time(whole request)--header,--post-data,--post-file— supported-c/--continue— supported —Range: bytes=<existing>-when output file exists; 206 appends, 200 replaces full file-V/-h— supported- Recursive / spider / FTP / WARC — out of scope
--no-clobber/-nc— supported — Skip download when the target file already exists and has size > 0 (not combined with--continue)-Ntimestamping — out of scope
Fetch / bare-fetch vs curl (-I + -L)
curl sends HEAD, and after a 3xx follows with GET on the new URL. bare-fetch reuses the original Request init on redirect, so HEAD stays HEAD on every hop, which breaks many servers/CDNs.
We do not depend on bare-fetch for that case: fetchHeadWithLocationFollow implements manual hops (HEAD → GET after redirect). See Upstream (bare-fetch) below if you want this fixed in the library.
Upstream (bare-fetch)
Tracking: Bare OS implements curl -I -L with manual redirects so the first hop can stay HEAD and a 3xx response can be followed with GET (see fetchHeadWithLocationFollow). Consider an upstream bare-fetch option for “curl-like” redirect method switching so other callers get the same behavior without a custom loop.
Issue tracker row (keep updated):
| Area | Upstream repo | Issue / PR | Status | Last checked |
|---|---|---|---|---|
HEAD + redirect method switching (curl -I -L semantics) |
holepunchto/bare-fetch |
TBD (add link once filed) | open | 2026-04-26 |
When the issue is filed, replace _TBD_ with the direct GitHub URL and keep this row current during release checklist updates.
Suggested issue title: Redirect following preserves original method (HEAD on every hop); optional curl-like mode?
Body (paste into GitHub):
When using
fetch(url, { method: 'HEAD', redirect: 'follow' }), redirects reuse the outerinit, so each hop stays HEAD. Real curl -IL uses HEAD on the first request, then GET after a redirect. That behavior matters for CDNs that return 302 to a URL that only answers GET.Request: Document this as spec-accurate Fetch behavior, and/or add an option (e.g. on
Requestinit or fetch options) to switch redirect method to GET after a redirect when the initial method was HEAD, matching common CLI expectations.Context: Bare OS implements a fetch-based
curlshim and currently usesredirect: 'manual'plus manual hops for-I -Linstead ofredirect: 'follow'for that reason.
Repository: holepunchto/bare-fetch. Workspace pin is bare-fetch@^3.2.0 (major 3: Headers.getSetCookie(), response.type). In-guest web_fetch forwards those fields when present.