use bytes::Bytes;
#[derive(Debug)]
#[must_use]
pub enum FilterAction {
Continue,
Reject(Rejection),
Release,
}
#[derive(Debug)]
#[must_use]
pub struct Rejection {
pub body: Option<Bytes>,
pub headers: Vec<(String, String)>,
pub status: u16,
}
impl Rejection {
pub fn status(code: u16) -> Self {
Self {
status: code,
headers: Vec::new(),
body: None,
}
}
pub fn with_header(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
self.headers.push((name.into(), value.into()));
self
}
pub fn with_body(mut self, body: impl Into<Bytes>) -> Self {
self.body = Some(body.into());
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rejection_status_defaults() {
let r = Rejection::status(404);
assert_eq!(r.status, 404, "status should match constructor arg");
assert!(r.headers.is_empty(), "headers should default to empty");
assert!(r.body.is_none(), "body should default to None");
}
#[test]
fn rejection_with_header_appends() {
let r = Rejection::status(403)
.with_header("X-Reason", "forbidden")
.with_header("X-Request-Id", "abc");
assert_eq!(r.headers.len(), 2, "should have two appended headers");
assert_eq!(
r.headers[0],
("X-Reason".into(), "forbidden".into()),
"first header should match"
);
assert_eq!(
r.headers[1],
("X-Request-Id".into(), "abc".into()),
"second header should match"
);
}
#[test]
fn rejection_with_body_sets_bytes() {
let r = Rejection::status(400).with_body(b"bad request".as_slice());
assert_eq!(
r.body.unwrap(),
Bytes::from_static(b"bad request"),
"body should contain provided bytes"
);
}
#[test]
fn filter_action_continue_variant() {
assert!(
matches!(FilterAction::Continue, FilterAction::Continue),
"Continue should match Continue"
);
}
#[test]
fn filter_action_reject_carries_rejection() {
let action = FilterAction::Reject(Rejection::status(503));
assert!(
matches!(action, FilterAction::Reject(r) if r.status == 503),
"Reject should carry rejection with status 503"
);
}
#[test]
fn filter_action_release_variant() {
assert!(
matches!(FilterAction::Release, FilterAction::Release),
"Release should match Release"
);
}
}