Features
The plan for 1.0. Each item names the version that ships it.
Parsing
- urlencoded (0.3) - the WHATWG algorithm with strict refusal:
&is the only separator, a malformed%and invalid UTF-8 are refused, never replaced. Zero copy when nothing needs decoding; a decoder that writes into your buffer and never allocates. - Streaming multipart (0.3) - sans-IO: bytes in, events out, identical for every split of the input. The boundary search is linear and never rescans a byte.
- Strict framing (0.3) - bare LF, header folding, duplicate headers and parameters, transfer encodings, nested multipart,
\"in quoted values, and a missing close delimiter are refused: the constructs where a firewall in front and the application behind could disagree. no_stdcore (0.3) - the Tier 3 parsers run withoutalloc, on buffers you provide.
Uploads
- Safe spilling (0.4) - files over a threshold go to temporary files in a private directory, created with random names and
create_new, owner-only, deleted on drop and on abort; in the default mode the operating system removes them if the process dies. - Disk budgets (0.4, 0.5) - a limit per request and a budget shared across requests (pluggable, so it can cover a host or a fleet); the request that would cross it is refused with a 503 hint.
- File names as data (0.3, 0.4) - raw bytes, base name, a sanitized portable name, an NFC form; never a path.
Integration
- Inspection hooks (0.4) - an inspector sees every part head, the first bytes of every file, and every field before anything is stored, in one pass.
- Anti-forgery token first (0.4) - the token field is captured, and a file that arrives before it is refused, so a forged upload costs no disk.
- Typed forms without serde (0.4) - one declarative macro; unknown, repeated, and missing fields refused; errors name the field, never echo input.
- Client side (0.3, 0.5) - a urlencoded serializer and a multipart writer whose output always parses back to the same fields.
Installation
[]
= "0.3"
Without default features the crate is no_std and needs no allocator: the allocation-free core (raw_pairs, decode_into, MultipartParser::with_buffer) works on any target. Add features = ["alloc"] for the owned results.
Quick start
The API below is fixed by the design lock; the 0.3 parts work today, the 0.4 parts arrive next.
use form_net as fnet;
// A urlencoded body (0.3)
let form = parse_urlencoded?;
assert_eq!;
// A query string (0.3)
let query = parse_query?;
assert_eq!;
// A buffered multipart body (0.3)
let mp = parse_multipart?;
let title = mp.field.unwrap_or;
// A typed form, either encoding (0.4)
form!
let login = from_body?;
// An upload streamed to private temporary files (0.4, feature `fs`)
let upload = read_multipart?;
if let Some = upload.file
Configuration (limits per route, policies, inspectors, stores) and the allocation-free Tier 3 surface are in docs/API.md.
Scope
form-net decides whether bytes are a well-formed form. Whether the form is acceptable for a route (schemas, allowed file types by content, Unicode rules) is customs-sec's job; whether the request came from the site's own page is csrf-sec's. HTTP framing is http-net's. See dev/PLAN.md for the full scope, what is deliberately left to other crates, the threat model, and the decision log.
Documentation
docs/API.md- every public item, with signatures, behaviour, errors, and examples.dev/PLAN.md- design, requirements, threats, performance targets, decisions.dev/ROADMAP.md- versions and exit criteria.CHANGELOG.mdanddocs/release/.
Contributing
See dev/DIRECTIVES.md for engineering standards and the definition of done. Before a PR: cargo fmt --all, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all-features must be clean.