~ober/jerboa-https
Imported from ~/mine/jerboa-https
about
# chez-https
Native HTTP/1.1 client over TLS for Chez Scheme. No subprocesses. No curl. Pure in-process HTTPS.
## Dependencies
- `jerboa-ssl` — TLS transport layer, locked by commit and tree in
`dependencies.lock`
- Chez Scheme 10.x
- OpenSSL (`libssl`, `libcrypto`)
## Installation
```bash
# From this checkout, fetch the reviewed dependency revision.
support/locked-dependency.sh fetch dependencies.lock jerboa-ssl ~/mine/jerboa-ssl
make
```
CI uses the same lock verifier. Updating `jerboa-ssl` requires a reviewed
commit and tree-hash change in `dependencies.lock`; default branches are never
consumed by the build.
## Usage
```scheme
(import (chez-https))
;; Simple GET
(let ([req (http-get "https://example.com/")])
(display (request-status req)) ;; 200
(display (request-text req)) ;; HTML body as string
(request-close req))
;; With headers and query parameters (S3-compatible format)
(let ([headers (list (list "Authorization" ':: "AWS4-HMAC-SHA256 ...")
'::
(list "Host" ':: "bucket.s3.amazonaws.com")
(list "x-amz-date" ':: "20260306T120000Z"))]
[params (list (list "list-type" ':: "2")
(list "prefix" ':: "AWSLogs/"))])
(let ([req (http-get url 'headers: headers 'params: params)])
(display (request-status req))
(request-close req)))
;; PUT with body
(let ([req (http-put url
'headers: headers
'params: #f
'data: (string->utf8 "request body"))])
(display (request-status req))
(request-close req))
```
## API
### HTTP Methods
```scheme
(http-get url ['headers: hdrs] ['params: params])
(http-post url ['headers: hdrs] ['params: params] ['data: body])
(http-put url ['headers: hdrs] ['params: params] ['data: body])
(http-delete url ['headers: hdrs] ['params: params])
(http-head url ['headers: hdrs] ['params: params])
```
### Response Accessors
| Function | Returns | Description |
|----------|---------|-------------|
| `(request-status req)` | integer | HTTP status code (200, 404, etc.) |
| `(request-text req)` | string | Response body as UTF-8 string |
| `(request-content req)` | bytevector | Response body as raw bytes |
| `(request-headers req)` | alist | Response headers (lowercase keys) |
| `(request-header req name)` | string or `#f` | Single header value lookup |
| `(request-close req)` | void | No-op (connection already closed) |
### Utilities
| Function | Description |
|----------|-------------|
| `(parse-url url)` | Returns `(values host port path)` |
| `(url-encode str)` | RFC 3986 percent-encoding |
| `(flatten-request-headers hdrs)` | Flatten `(name :: value)` format to alist |
| `(build-query-string params)` | Build URL query string from params |
### Response policy
`(http-client-config)` returns the active bounded response policy. Set startup
limits with options such as `max-header-bytes:`, `max-headers:`, `max-body:`,
`max-chunk:`, `max-chunked-wire:`, `idle-timeout:`, and `total-timeout:`.
Values must be positive exact integers. Configure the policy before issuing
concurrent requests.
## Features
- HTTPS via OpenSSL (TLS 1.2/1.3)
- SNI and hostname verification
- Streaming, bounded chunked transfer decoding
- Strict duplicate/conflicting response-framing rejection
- Header, decoded-body, raw-chunked-body, chunk-size, idle, and total limits
- RFC-token/control-character validation before request serialization
- 100 Continue handling
- Binary response body preservation (critical for gzip/binary downloads)
- Configurable HTTPD worker count, listen backlog, queue capacity, request
timeout, response timeout, header count, and body size limits
- Bounded TLS handshake workers, queue, short handshake deadline, and
global/per-IP pre-authentication limits
- Descriptor-pinned static-file serving with canonical containment and inode
identity verification
- S3-compatible header format (`::` separator convention)
- URL encoding (RFC 3986)
- Automatic SSL initialization
## Testing
```bash
make test
```
The tests include a local self-signed TLS peer for hostile response framing and
deadline cases. Interpreter-based development explicitly opts into loading
`jerboa-ssl` from its canonical absolute directory; production binaries should
statically register the TLS shim.
## Release Evidence
The HTTPD surface is private until the daemon release gate is complete. Run:
```bash
make release-evidence
```
The release bundle includes SBOM, reproducibility, TLS dependency, HTTPD
fuzz-evidence, and HTTPD soak status under `dist/release-evidence/`. Default
fuzz evidence records fixed adversarial cases, a 2048-case generated
deterministic HTTPD corpus, and a present cargo-fuzz harness for the sandboxed
HTTP parser. Run with `JHTTPS_RUN_COVERAGE_FUZZ=1` to record bounded local
coverage evidence; production release still requires longer release-host fuzz
evidence or a signed exception. Default local soak evidence records load and queue-exhaustion
soak as blocked/not-run. Opt-in local soak evidence records deterministic
slow-client coverage plus bounded load/queue smokes, but production release
still requires target-host sustained load evidence.
HTTPD TLS/proxy policy is documented in `docs/tls-proxy-policy.md` and copied
into `dist/release-evidence/tls-proxy-policy.txt`.
## Architecture
```
chez-https (this library)
│
└── jerboa-ssl (TLS transport)
│
└── OpenSSL (libssl, libcrypto)
```
`chez-https` is Scheme on top of `chez-ssl` for I/O. The HTTPD parser boundary
uses a small Rust/WASM sandbox for request lines, header lines, and chunk sizes
when the Jerboa WASM sandbox is available; `JHTTPS_REQUIRE_WASM_HTTP=1` makes
that boundary fail closed for production deployments.
recent commits
- Document local mine repository authority 23590c8 Jaime Fournier
- Use FreeBSD Forgejo CI runner 11c4dd7 user
- Set up Forgejo CI/CD policy aff22a3 Jaime Fournier
- Update jpkg metadata for Forgejo 2ceb336 Jaime Fournier
- docs: remove jerboa-emacs restriction 33b5e3d Jaime Fournier
- Remove GitHub workflow metadata 488e067 Jaime Fournier
- update AGENTS.md c2832f9 Jaime Fournier
- build: remove tracked generated .sls files and ignore them 0cddc00 Jaime Fournier
- docs: note ~/.local/bin/jerboa path in AGENTS.md 4851970 Jaime Fournier
- Add vendoring policy to AGENTS.md 8f29a7f Jaime Fournier