huginn_net_http/matcher_api.rs
1//! HTTP matcher trait owned by `huginn-net-http`.
2//!
3//! Mirrors `huginn_net_tcp::matcher_api::TcpMatcher`. Any consumer that wants
4//! HTTP signature matching feeds an implementation of this trait into
5//! [`crate::HuginnNetHttp`]. The reference implementation lives in
6//! `huginn-net-db` (`HttpSignatureMatcher` and `SharedHttpSignatureMatcher`),
7//! but downstream users are free to plug their own.
8
9use crate::observable::{HttpRequestObservation, HttpResponseObservation};
10use crate::output::{Browser, MatchRank, WebServer};
11
12/// Result of matching an [`HttpRequestObservation`] against a database.
13/// `dishonest` is set when the User-Agent does not back the matched signature.
14#[derive(Debug, Clone)]
15pub struct HttpRequestMatch {
16 pub browser: Browser,
17 pub rank: MatchRank,
18 pub dishonest: bool,
19}
20
21/// Result of matching an [`HttpResponseObservation`] against a database.
22/// `dishonest` is set when the Server header does not back the matched signature.
23#[derive(Debug, Clone)]
24pub struct HttpResponseMatch {
25 pub web_server: WebServer,
26 pub rank: MatchRank,
27 pub dishonest: bool,
28}
29
30/// Result of mapping a User-Agent string against the database's UA→OS table.
31///
32/// `family` is the OS family (e.g. `"Windows"`, `"Linux"`); `flavor` is the
33/// optional sub-variant (e.g. `"7 or 8"`).
34#[derive(Debug, Clone)]
35pub struct UaOsMatch {
36 pub family: String,
37 pub flavor: Option<String>,
38}
39
40/// Pluggable HTTP signature matcher.
41///
42/// Implementations must be `Send + Sync` so they can be shared across the
43/// worker threads spawned by [`crate::HuginnNetHttp`].
44pub trait HttpMatcher: Send + Sync {
45 /// Match an HTTP request observation. Returns `None` if no candidate
46 /// signature meets the configured quality threshold.
47 fn match_http_request(&self, obs: &HttpRequestObservation) -> Option<HttpRequestMatch>;
48
49 /// Match an HTTP response observation.
50 fn match_http_response(&self, obs: &HttpResponseObservation) -> Option<HttpResponseMatch>;
51
52 /// Map a User-Agent string against the database UA→OS table.
53 fn match_user_agent(&self, ua: &str) -> Option<UaOsMatch>;
54}