87 lines
4.5 KiB
Markdown
87 lines
4.5 KiB
Markdown
# Curl for the world
|
|
|
|
This CLI sends HTTP and HTTPS requests through standard WASI HTTP.
|
|
The host supplies TLS and transparent credential injection.
|
|
The CLI does not request or read host credentials.
|
|
Each redirect creates a separate request, so the host checks every hop.
|
|
Every request has Content-Length, including empty requests.
|
|
The client finishes the body before it waits for a response.
|
|
It does not flush or poll the outgoing stream after its final byte.
|
|
A fast peer can close that stream after it consumes the framed body.
|
|
Verbose request output contains only headers that the CLI supplies.
|
|
|
|
## Supported options
|
|
|
|
- A positional HTTP or HTTPS URL. A URL without a scheme defaults to HTTP.
|
|
- `-X`, `--request` selects the method.
|
|
- Repeatable `-H`, `--header` overrides defaults or adds headers. An empty value suppresses a default header.
|
|
- `-d`, `--data` reads literal data, `@file`, or `@-`. File input removes CR, LF, and NUL bytes.
|
|
- `--data-raw` treats all input literally, including an initial `@`.
|
|
- `--data-binary` preserves file and stdin bytes.
|
|
- Data options imply POST and the form content type. Repeated data options join with `&` in argument order.
|
|
- `--json` implies POST, preserves its body, and sets JSON Content-Type and Accept headers.
|
|
- `-o`, `--output` writes to a world file. `-o -` writes to stdout.
|
|
- `-O`, `--remote-name` uses the original URL's last path segment.
|
|
- `-s`, `--silent` suppresses errors. `-S`, `--show-error` restores errors with silent mode.
|
|
- `-i`, `--include` includes response headers. `-I`, `--head` selects HEAD and prints headers.
|
|
- `-L`, `--location` follows redirects. `--max-redirs` defaults to 50. A negative value removes the limit.
|
|
- Redirects 301, 302, and 303 convert POST to GET. Redirects 307 and 308 preserve the body.
|
|
- Redirects to another origin remove explicit Authorization and Cookie headers.
|
|
- `-f`, `--fail` suppresses error bodies and returns 22 for status codes of at least 400.
|
|
- `--fail-with-body` returns 22 but retains the body.
|
|
- `-w`, `--write-out` supports `%{http_code}`, `%{url_effective}`, `%{content_type}`, `%{size_download}`, and `\n`.
|
|
- `-v`, `--verbose` prints request and response headers to stderr.
|
|
- `-u`, `--user` supplies Basic authentication. A missing password uses an empty password without a prompt.
|
|
- `-A`, `--user-agent` supplies the User-Agent header.
|
|
- `-k`, `--insecure` is accepted and ignored. The host controls TLS verification.
|
|
- `-m`, `--max-time` bounds network operations across redirects. Zero removes the deadline.
|
|
- `--help` prints the CLI's supported options.
|
|
|
|
Unknown options return 2 with curl's unknown-option message.
|
|
HTTP failures return 22 only when a fail option applies.
|
|
Network deadlines return 28. Input errors return 26. Output errors return 23.
|
|
|
|
## Known differences
|
|
|
|
The CLI supports one URL per invocation.
|
|
It does not implement multipart `-F`, `--compressed`, or curl's other options.
|
|
It buffers request and response bodies. It does not show a progress meter.
|
|
The default User-Agent is `curl/8.0.0`, not the native curl version.
|
|
WASI exposes the status code, but not the HTTP version or reason phrase.
|
|
The CLI reconstructs header status lines as HTTP/1.1 with standard reason phrases for common codes.
|
|
The host can normalize response header names and order.
|
|
WASI omits hop-by-hop headers, such as Connection, from the response.
|
|
WASI rejects forbidden request headers. The CLI sets Content-Length from the body size.
|
|
Verbose output omits native curl's connection and TLS diagnostics.
|
|
Transport diagnostics describe WASI errors instead of native libcurl errors.
|
|
Argument diagnostics other than unknown options use clap's text with exit code 2.
|
|
Write-out supports only the listed substitutions and a literal format string.
|
|
The CLI does not implement curl's credential prompts, cookie jar, config file, or proxy options.
|
|
|
|
## Validation
|
|
|
|
Run these commands from `userland/`:
|
|
|
|
```sh
|
|
CARGO_BUILD_JOBS=2 CARGO_TARGET_DIR=/tmp/p1-curl/target nix develop .. -c cargo build -p curl --release --locked
|
|
```
|
|
|
|
The shared `cwd-init/init.o` must exist first. Generate it from the repository root if needed:
|
|
|
|
```sh
|
|
nix develop -c nu userland/cwd-init/build.nu
|
|
```
|
|
|
|
Run the comparisons from the repository root:
|
|
|
|
```sh
|
|
nix develop -c nu userland/curl/test.nu
|
|
```
|
|
|
|
The script builds the native fixture with a persistent cache and starts it on a free port.
|
|
Each run uses a fresh readiness file.
|
|
The script stops the fixture after success or failure.
|
|
The script compares deterministic local responses with native curl.
|
|
It also checks a public HTTPS GET and verifies WASI-only component imports.
|
|
The script retains its temporary files for inspection.
|