use crate::{
HttpVersion, Result, cert::{Certificate, Identity}, request::{Http1Request, Http2Request}, response::DeboaResponse,
};
use http::{Request, Response, Version};
use http_body::Body;
use hyper_body_utils::HttpBody;
use std::{collections::HashMap, error::Error, future::Future, marker::PhantomData, net::IpAddr, sync::Arc};
use time::Duration;
use url::Url;
pub trait HttpConnection {
type Sender;
fn sender(&mut self) -> &mut Self::Sender;
}
pub struct ConnectionConfigBuilder<'a, I, C> {
is_secure: bool,
ip: IpAddr,
host: &'a str,
port: u16,
protocol: HttpVersion,
identity: Option<I>,
certificate: Option<C>,
skip_cert_verification: bool,
client_bind_addr: IpAddr,
}
impl<'a, I, C> ConnectionConfigBuilder<'a, I, C>
where
I: Identity,
C: Certificate,
{
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self {
is_secure: false,
ip: "127.0.0.1"
.parse::<IpAddr>()
.unwrap(),
host: "",
port: 80,
protocol: HttpVersion::Http2,
identity: None,
certificate: None,
skip_cert_verification: false,
client_bind_addr: "0.0.0.0"
.parse()
.unwrap(),
}
}
pub fn is_secure(mut self, is_secure: bool) -> Self {
self.is_secure = is_secure;
self
}
pub fn ip(mut self, ip: IpAddr) -> Self {
self.ip = ip;
self
}
pub fn host(mut self, host: &'a str) -> Self {
self.host = host;
self
}
pub fn port(mut self, port: u16) -> Self {
self.port = port;
self
}
pub fn protocol(mut self, protocol: HttpVersion) -> Self {
self.protocol = protocol;
self
}
pub fn identity(mut self, identity: Option<I>) -> Self {
self.identity = identity;
self
}
pub fn certificate(mut self, certificate: Option<C>) -> Self {
self.certificate = certificate;
self
}
pub fn skip_cert_verification(mut self, skip_cert_verification: bool) -> Self {
self.skip_cert_verification = skip_cert_verification;
self
}
pub fn client_bind_addr(mut self, client_bind_addr: IpAddr) -> Self {
self.client_bind_addr = client_bind_addr;
self
}
pub fn build(self) -> ConnectionConfig<'a, I, C> {
ConnectionConfig {
is_secure: self.is_secure,
ip: self.ip,
host: self.host,
port: self.port,
protocol: self.protocol,
identity: self.identity,
certificate: self.certificate,
skip_cert_verification: self.skip_cert_verification,
client_bind_addr: self.client_bind_addr,
}
}
}
pub struct ConnectionConfig<'a, I, C> {
is_secure: bool,
ip: IpAddr,
host: &'a str,
port: u16,
protocol: HttpVersion,
identity: Option<I>,
certificate: Option<C>,
skip_cert_verification: bool,
client_bind_addr: IpAddr,
}
impl<'a, I, C> ConnectionConfig<'a, I, C>
where
I: Identity,
C: Certificate,
{
pub fn builder() -> ConnectionConfigBuilder<'a, I, C> {
ConnectionConfigBuilder::new()
}
pub fn is_secure(&self) -> bool {
self.is_secure
}
pub fn ip(&self) -> &IpAddr {
&self.ip
}
pub fn host(&self) -> &str {
self.host
}
pub fn port(&self) -> u16 {
self.port
}
pub fn protocol(&self) -> &HttpVersion {
&self.protocol
}
pub fn identity(&self) -> &Option<I> {
&self.identity
}
pub fn certificate(&self) -> &Option<C> {
&self.certificate
}
pub fn skip_cert_verification(&self) -> bool {
self.skip_cert_verification
}
pub fn client_bind_addr(&self) -> &IpAddr {
&self.client_bind_addr
}
}
pub trait ProtoConnection {
type ReqBody: Body + Unpin;
type ResBody: Body + Unpin;
type Connection: HttpConnection;
type Identity: crate::cert::Identity;
type Certificate: crate::cert::Certificate;
fn connect(
config: &ConnectionConfig<Self::Identity, Self::Certificate>,
) -> impl Future<Output = Result<Self::Connection>>;
fn protocol(&self) -> Version;
}
pub trait HttpConnectionPool {
type Identity: crate::cert::Identity;
type Certificate: crate::cert::Certificate;
type ConnectionDispather: HttpConnectionDispatcher;
fn new(max_idle_connections: u32, keep_alive_duration: Duration) -> Self;
fn connections(&self) -> &HashMap<String, Self::ConnectionDispather>;
fn connection_count(&self) -> u32;
fn create_connection<'a>(
&'a mut self,
config: &ConnectionConfig<'a, Self::Identity, Self::Certificate>,
) -> impl Future<Output = Result<&'a mut Self::ConnectionDispather>>;
}
pub trait HttpConnectionDispatcher {
fn send_request(
&mut self,
url: Arc<Url>,
request: Request<HttpBody>,
) -> impl Future<Output = Result<DeboaResponse>>;
}
pub struct SendRequest<Sender, Body> {
sender: Sender,
_p: PhantomData<Body>
}
impl<Sender, Body> SendRequest<Sender, Body> {
pub fn new(sender: Sender) -> Self {
Self { sender, _p: PhantomData }
}
}
impl SendRequest<Http1Request, HttpBody> {
pub async fn send_request(&mut self, request: Request<HttpBody>) -> std::result::Result<Response<HttpBody>, Box<dyn Error>> {
let response = self
.sender
.send_request(request)
.await?;
let (parts, body) = response.into_parts();
Ok(Response::from_parts(parts, HttpBody::from_incoming(body)))
}
}
impl SendRequest<Http2Request, HttpBody> {
pub async fn send_request(&mut self, request: Request<HttpBody>) -> std::result::Result<Response<HttpBody>, Box<dyn Error>> {
let response = self
.sender
.send_request(request)
.await?;
let (parts, body) = response.into_parts();
Ok(Response::from_parts(parts, HttpBody::from_incoming(body)))
}
}