pub trait Inspector {
// Provided methods
fn part_start(&mut self, head: &PartHead<'_>) -> Verdict { ... }
fn sniff(&mut self, head: &PartHead<'_>, first: &[u8]) -> Verdict { ... }
fn data(&mut self, part: u32, chunk: &[u8]) -> Verdict { ... }
fn field(&mut self, name: &str, value: &[u8]) -> Verdict { ... }
fn part_end(&mut self, summary: &PartSummary) -> Verdict { ... }
fn end(&mut self) -> Verdict { ... }
fn failed(&mut self, error: &FormError) { ... }
}Expand description
Takes part in a parse: called for every part head, the first bytes of every file, every data chunk, every complete text field, every part end, the end of the body, and once on any failure.
Every method has a default, so an inspector implements only what it checks.
Order guarantee, per part and at every split of the input:
part_start ─▶ sniff (file parts, when sniff_bytes > 0) ─▶ data* ─▶ field (text fields) ─▶ part_end
... after the last part: end
... on any error, at any point: failed (once), then the error is returnedFor urlencoded bodies only field, end, and failed are called.
§Examples
use form_net::{Inspector, PartHead, Refusal, Verdict};
/// Allows only PNG and JPEG avatars, judged by their bytes.
struct ImagesOnly;
impl Inspector for ImagesOnly {
fn part_start(&mut self, head: &PartHead<'_>) -> Verdict {
match (head.name(), head.is_file()) {
("avatar", true) | ("title", false) => Verdict::Continue,
_ => Verdict::Refuse(Refusal::new(422, "example.unexpected_field")),
}
}
fn sniff(&mut self, _head: &PartHead<'_>, first: &[u8]) -> Verdict {
if first.starts_with(b"\x89PNG\r\n\x1a\n") || first.starts_with(b"\xff\xd8\xff") {
Verdict::Continue
} else {
Verdict::Refuse(Refusal::new(415, "example.avatar_not_image"))
}
}
}Provided Methods§
Sourcefn part_start(&mut self, head: &PartHead<'_>) -> Verdict
fn part_start(&mut self, head: &PartHead<'_>) -> Verdict
A part’s headers were read and passed every rule. Called before any byte of the part reaches a sink.
Sourcefn sniff(&mut self, head: &PartHead<'_>, first: &[u8]) -> Verdict
fn sniff(&mut self, head: &PartHead<'_>, first: &[u8]) -> Verdict
The first min(sniff_bytes, part length) bytes of a file part, as one
contiguous slice however the input was split, before any data call
for that part.
Sourcefn data(&mut self, part: u32, chunk: &[u8]) -> Verdict
fn data(&mut self, part: u32, chunk: &[u8]) -> Verdict
Bytes of part part’s data, text fields included.
Sourcefn field(&mut self, name: &str, value: &[u8]) -> Verdict
fn field(&mut self, name: &str, value: &[u8]) -> Verdict
A complete text field (multipart) or a decoded pair (urlencoded): the
value as bytes, so the inspector can apply its own charset rules.
Skip leaves the field out of the result.
Sourcefn part_end(&mut self, summary: &PartSummary) -> Verdict
fn part_end(&mut self, summary: &PartSummary) -> Verdict
A part ended. Skip here is treated as Continue.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementations on Foreign Types§
Source§impl<A: Inspector, B: Inspector> Inspector for (A, B)
Two inspectors in one pass, self.0 first (D-088). A refusal from either
wins and the second is not asked; otherwise the part is skipped if either
says Skip. failed reaches both. Nest pairs for longer chains:
(customs, (sentinel, app)).
impl<A: Inspector, B: Inspector> Inspector for (A, B)
Two inspectors in one pass, self.0 first (D-088). A refusal from either
wins and the second is not asked; otherwise the part is skipped if either
says Skip. failed reaches both. Nest pairs for longer chains:
(customs, (sentinel, app)).
§Examples
use form_net::{Inspector, Limits, Policy, Refusal, Verdict};
struct NoAdmin;
impl Inspector for NoAdmin {
fn field(&mut self, _name: &str, value: &[u8]) -> Verdict {
if value == b"admin" { Verdict::Refuse(Refusal::new(403, "app.admin")) } else { Verdict::Continue }
}
}
struct Count(u32);
impl Inspector for Count {
fn field(&mut self, _name: &str, _value: &[u8]) -> Verdict {
self.0 += 1;
Verdict::Continue
}
}
let mut chain = (Count(0), NoAdmin);
let r = form_net::parse_urlencoded_inspected(b"a=1&b=admin", &Limits::DEFAULT, &Policy::DEFAULT, &mut chain);
assert_eq!(r.unwrap_err().status_hint(), 403);
assert_eq!(chain.0 .0, 2);fn part_start(&mut self, head: &PartHead<'_>) -> Verdict
fn sniff(&mut self, head: &PartHead<'_>, first: &[u8]) -> Verdict
fn data(&mut self, part: u32, chunk: &[u8]) -> Verdict
fn field(&mut self, name: &str, value: &[u8]) -> Verdict
fn part_end(&mut self, summary: &PartSummary) -> Verdict
fn end(&mut self) -> Verdict
fn failed(&mut self, error: &FormError)
Source§impl<I: Inspector + ?Sized> Inspector for &mut I
impl<I: Inspector + ?Sized> Inspector for &mut I
fn part_start(&mut self, head: &PartHead<'_>) -> Verdict
fn sniff(&mut self, head: &PartHead<'_>, first: &[u8]) -> Verdict
fn data(&mut self, part: u32, chunk: &[u8]) -> Verdict
fn field(&mut self, name: &str, value: &[u8]) -> Verdict
fn part_end(&mut self, summary: &PartSummary) -> Verdict
fn end(&mut self) -> Verdict
fn failed(&mut self, error: &FormError)
Source§impl<I: Inspector + ?Sized> Inspector for Box<I>
Available on crate feature alloc only.A boxed inspector, for a chain chosen at run time (D-088).
impl<I: Inspector + ?Sized> Inspector for Box<I>
alloc only.A boxed inspector, for a chain chosen at run time (D-088).