#[cfg(feature = "decoder")]
mod decoder;
mod proxy;
mod rewind;
pub mod certificate_authority;
use std::convert::Infallible;
use std::future::Future;
use std::io::Read;
use hyper::{Request, Response, Uri};
use std::net::SocketAddr;
use tokio_tungstenite::tungstenite::Message;
pub(crate) use rewind::Rewind;
pub use async_trait::async_trait;
use bytes::Bytes;
pub use hyper;
use hyper::header::{HeaderName, HeaderValue, InvalidHeaderName};
use product_os_http::HeaderMap;
use product_os_http_body::{BodyBytes as Body, BodyBytes, BodyError};
pub use product_os_http_body::BodyError as Error;
pub use tokio_rustls::rustls;
pub use tokio_tungstenite;
#[cfg(feature = "decoder")]
pub use decoder::{decode_request, decode_response};
#[cfg(feature = "vpn")]
use product_os_request::ProductOSResponse;
pub use proxy::*;
#[derive(Debug)]
pub enum RequestOrResponse {
Request(Request<Body>),
Response(Response<Body>),
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct HttpContext {
pub client_addr: SocketAddr,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum WebSocketContext {
ClientToServer {
src: SocketAddr,
dst: Uri,
},
ServerToClient {
src: Uri,
dst: SocketAddr,
},
}
#[async_trait]
pub trait HttpHandler: Clone + Send + Sync + 'static {
async fn handle_request(
&mut self,
_ctx: &HttpContext,
request: Request<Body>,
) -> RequestOrResponse {
RequestOrResponse::Request(request)
}
async fn handle_response(
&mut self,
_ctx: &HttpContext,
_: Request<Body>, response: Response<Body>,
) -> Response<Body> {
response
}
#[cfg(feature = "vpn")]
async fn handle_product_os_response(
&mut self,
_ctx: &HttpContext,
_: Request<Body>, response: ProductOSResponse<Body>,
) -> Response<Body> {
let status = response.status();
let mut headers = HeaderMap::new();
for (name, value) in &response.get_headers() {
let header_name = match HeaderName::from_bytes(name.as_bytes()) {
Ok(name) => name,
Err(e) => {
tracing::error!("Error with header kind: {:?}", e);
continue
}
};
let header_value = HeaderValue::from_str(value.as_str()).unwrap();
headers.insert(header_name, header_value);
}
let (_, mut body) = response.parts();
let body_bytes = match body.as_bytes().await {
Ok(bytes) => bytes.to_vec(),
Err(e) => {
tracing::error!("Error converting body to bytes: {:?}", e);
Vec::new()
}
};
let response_body = Body::new(Bytes::from(body_bytes));
let mut response_to_return = Response::builder();
for (name, value) in headers {
match name {
None => {}
Some(name) => { response_to_return = response_to_return.header(name, value); }
}
}
response_to_return = response_to_return.status(status);
response_to_return.body(response_body).unwrap()
}
fn should_intercept(
&mut self,
_ctx: &HttpContext,
_req: &Request<Body>,
) -> impl Future<Output = bool> + Send {
async { true }
}
}
#[async_trait]
pub trait WebSocketHandler: Clone + Send + Sync + 'static {
async fn handle_message(
&mut self,
_ctx: &WebSocketContext,
message: Message,
) -> Option<Message> {
Some(message)
}
}