web_net/events.rs
1//! What web-net tells the rest of the system, and where it asks whether a
2//! request may continue.
3//!
4//! A security component that cannot report what it sees is a detour, not a
5//! defence. Every refusal, denial, and failure is reported through
6//! [`Events`], so a detection or gate layer hears about a probe the moment
7//! web-net turns it away. Events carry ids, codes, and statuses, never
8//! request bytes.
9
10use serve_net::{Envelope, Verdict};
11
12use crate::RequestId;
13
14/// What kind of thing happened.
15#[non_exhaustive]
16#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17pub enum EventKind {
18 /// Refused before a handler: a malformed path, an unknown host, no
19 /// route, a method the route does not take.
20 Refused,
21 /// A gate denied the request.
22 Denied,
23 /// A handler or render failed (any handler error, and every 5xx).
24 Failed,
25 /// A handler panicked; answered with 500.
26 Panicked,
27 /// A checkpoint stopped the request in flight.
28 Revoked,
29}
30
31/// One event.
32#[non_exhaustive]
33#[derive(Debug)]
34pub struct Event<'a> {
35 /// What happened.
36 pub kind: EventKind,
37 /// The request's reference.
38 pub id: RequestId,
39 /// The matched route's pattern, if routing got that far.
40 pub route: Option<&'a str>,
41 /// The status answered.
42 pub status: u16,
43 /// A stable code (`"url.encoded_slash"`, a gate's code, a handler's).
44 pub code: &'static str,
45 /// The underlying error, for the logs only.
46 pub source: Option<&'a (dyn std::error::Error + 'static)>,
47}
48
49/// Where web-net reports. Every method has an empty default; the default
50/// implementation, [`NoEvents`], reports nothing.
51///
52/// Called on the request path: keep it to a counter or a queue push.
53pub trait Events: Send + Sync + 'static {
54 /// One event.
55 fn event(&self, event: &Event<'_>) {
56 let _ = event;
57 }
58}
59
60/// Reports nothing.
61#[derive(Clone, Copy, Debug, Default)]
62pub struct NoEvents;
63
64impl Events for NoEvents {}
65
66/// A point in web-net's pipeline where a checkpoint runs.
67#[non_exhaustive]
68#[derive(Clone, Copy, Debug, PartialEq, Eq)]
69pub enum Stage {
70 /// After the route's access check passed, before any hook or handler.
71 Authorized,
72 /// Before a page is rendered.
73 BeforeRender,
74}
75
76/// Revocation in flight: a ban, a revoked session, or a lockdown that
77/// arrives while a request is being handled. serve-net's own checkpoint
78/// covers admission and the moment before the reply leaves; this one covers
79/// the points in between that only web-net knows.
80///
81/// A checkpoint backed by remote state fails closed (denies) when the
82/// remote cannot be reached.
83pub trait Checkpoint: Send + Sync + 'static {
84 /// Decides at one stage.
85 fn check(&self, env: &Envelope, at: Stage) -> Verdict;
86}