leyline-http 0.1.5

HTTP client that impersonates Chrome, Firefox, and Safari on the wire: TLS (JA3/JA4), HTTP/2, and HTTP/3 fingerprints
Documentation
#[cfg(feature = "websocket")]
use std::io;
use std::sync::Arc;

use bytes::Bytes;
#[cfg(feature = "websocket")]
use tokio::sync::mpsc;
use tokio::sync::oneshot;

use crate::h2::connection::{HeaderPair, PseudoHeaders};

use super::ResponseSink;

pub(crate) const MAX_FLOW_WINDOW: i64 = 0x7FFF_FFFF;

pub(crate) fn checked_window_add(current: i64, delta: i64) -> Result<i64, i64> {
    let new_win = current.saturating_add(delta);
    if new_win > MAX_FLOW_WINDOW {
        Err(new_win)
    } else {
        Ok(new_win)
    }
}

pub(crate) enum DriverRequestBody {
    None,
    Buffered(Bytes),
    Streaming(crate::util::upload::BodyStream),
}

pub struct Head {
    pub pseudo: PseudoHeaders,
    pub headers: Vec<HeaderPair>,
}

pub(crate) enum DriverCommand {
    SendRequest {
        head: Arc<Head>,
        body: DriverRequestBody,
        sink: ResponseSink,
    },
    #[cfg(feature = "websocket")]
    OpenConnect {
        pseudo: PseudoHeaders,
        headers: Vec<crate::h2::connection::HeaderPair>,
        write_rx: mpsc::Receiver<io::Result<Bytes>>,
        sink: ResponseSink,
    },
    Ping {
        ack_tx: oneshot::Sender<()>,
    },
}

impl DriverCommand {
    pub(crate) fn is_cancelled(&self) -> bool {
        match self {
            DriverCommand::SendRequest { sink, .. } => sink.is_cancelled(),
            #[cfg(feature = "websocket")]
            DriverCommand::OpenConnect { sink, .. } => sink.is_cancelled(),
            DriverCommand::Ping { ack_tx } => ack_tx.is_closed(),
        }
    }

    pub(crate) fn into_sink(self) -> Option<ResponseSink> {
        match self {
            DriverCommand::SendRequest { sink, .. } => Some(sink),
            #[cfg(feature = "websocket")]
            DriverCommand::OpenConnect { sink, .. } => Some(sink),
            DriverCommand::Ping { .. } => None,
        }
    }
}

#[cfg(test)]
mod flow_control_tests;