Skip to main content

reqwest_proxy_pool/
classifier.rs

1//! Body-aware classification for proxy health feedback.
2
3/// Result of classifying a response body from a proxy.
4#[derive(Debug, Clone, Copy, PartialEq)]
5pub enum ProxyBodyVerdict {
6    /// Response is good. Proxy records a success.
7    Success,
8    /// Proxy is blocked (e.g. captcha, anti-bot). Records failure, retries with another proxy.
9    ProxyBlocked,
10    /// Server-side issue unrelated to proxy. Returns response as-is without affecting proxy stats.
11    Passthrough,
12}
13
14/// Classify responses with full body to determine proxy health at business level.
15///
16/// # Example
17/// ```rust,no_run
18/// use reqwest_proxy_pool::{BodyClassifier, ProxyBodyVerdict};
19///
20/// struct CaptchaDetector;
21///
22/// impl BodyClassifier for CaptchaDetector {
23///     fn classify(
24///         &self,
25///         status: reqwest::StatusCode,
26///         _headers: &reqwest::header::HeaderMap,
27///         body: &[u8],
28///     ) -> ProxyBodyVerdict {
29///         if status == reqwest::StatusCode::TOO_MANY_REQUESTS
30///             || String::from_utf8_lossy(body).contains("captcha")
31///         {
32///             ProxyBodyVerdict::ProxyBlocked
33///         } else if status.is_success() {
34///             ProxyBodyVerdict::Success
35///         } else {
36///             ProxyBodyVerdict::Passthrough
37///         }
38///     }
39/// }
40/// ```
41pub trait BodyClassifier: Send + Sync + 'static {
42    fn classify(
43        &self,
44        status: reqwest::StatusCode,
45        headers: &reqwest::header::HeaderMap,
46        body: &[u8],
47    ) -> ProxyBodyVerdict;
48}
49
50/// Default classifier: HTTP success = Success, otherwise Passthrough.
51pub struct DefaultBodyClassifier;
52
53impl BodyClassifier for DefaultBodyClassifier {
54    fn classify(
55        &self,
56        status: reqwest::StatusCode,
57        _headers: &reqwest::header::HeaderMap,
58        _body: &[u8],
59    ) -> ProxyBodyVerdict {
60        if status.is_success() {
61            ProxyBodyVerdict::Success
62        } else {
63            ProxyBodyVerdict::Passthrough
64        }
65    }
66}