diff --git a/.gitignore b/.gitignore index ddb7caf..7b2993a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,8 @@ # macOS files .DS_Store + +# Certificates +*.crt +*.key +*.pem diff --git a/Cargo.lock b/Cargo.lock index d1ae8e0..797410c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,6 +88,17 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "async-trait" +version = "0.1.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -146,6 +157,12 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076" +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "bindgen" version = "0.69.5" @@ -175,6 +192,15 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "boa_ast" version = "0.20.0" @@ -454,18 +480,47 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "dashmap" version = "6.1.0" @@ -489,6 +544,16 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -691,6 +756,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -762,6 +837,30 @@ dependencies = [ "foldhash", ] +[[package]] +name = "headers" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" +dependencies = [ + "base64", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http", +] + [[package]] name = "heck" version = "0.5.0" @@ -844,6 +943,44 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-http-proxy" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d06dbdfbacf34d996c6fb540a71a684a7aae9056c71951163af8a8a4c07b9a4" +dependencies = [ + "bytes", + "futures-util", + "headers", + "http", + "hyper", + "hyper-rustls", + "hyper-util", + "pin-project-lite", + "rustls-native-certs 0.7.3", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-native-certs 0.8.1", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-tls" version = "0.6.0" @@ -1136,6 +1273,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1174,7 +1317,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -1339,6 +1482,7 @@ dependencies = [ name = "pacman" version = "0.1.0" dependencies = [ + "async-trait", "boa_engine", "boa_parser", "bytes", @@ -1348,6 +1492,7 @@ dependencies = [ "http", "http-body-util", "hyper", + "hyper-http-proxy", "hyper-tls", "hyper-util", "pin-project-lite", @@ -1682,6 +1827,31 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "rustls-pki-types", + "schannel", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.2.0", +] + [[package]] name = "rustls-pemfile" version = "2.2.0" @@ -1749,7 +1919,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +dependencies = [ + "bitflags", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -1797,6 +1980,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "shlex" version = "1.3.0" @@ -2127,6 +2321,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-ident" version = "1.0.16" @@ -2163,6 +2363,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "want" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index bc2868c..0aa67fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ boa_parser = "0.20.0" tls-parser = "0.12.2" tokio-util = { version = "0.7.13", features = ["compat"] } pin-project-lite = "0.2.16" +async-trait = "0.1.75" [dependencies] bytes = { workspace = true } @@ -48,8 +49,10 @@ rustls-pemfile = { workspace = true } clap = { workspace = true } boa_engine = { workspace = true } boa_parser = { workspace = true } +hyper-tls = { workspace = true } tls-parser = { workspace = true } +async-trait = { workspace = true } tokio-util = { workspace = true } hyper-util = { workspace = true } -hyper-tls = { workspace = true } pin-project-lite = { workspace = true } +hyper-http-proxy = "1.0.0" diff --git a/src/conditions.rs b/src/conditions.rs index dcb4ddb..626eae6 100644 --- a/src/conditions.rs +++ b/src/conditions.rs @@ -1042,7 +1042,7 @@ mod condition_tests { #[cfg(test)] mod to_js_tests { - use crate::logic::{ToJs}; + use crate::logic::{PacExpression, ToJs}; use crate::proxy_types::ProxyType; use super::*; diff --git a/src/forwarder/direct.rs b/src/forwarder/direct.rs new file mode 100644 index 0000000..91c40f7 --- /dev/null +++ b/src/forwarder/direct.rs @@ -0,0 +1,44 @@ +use std::error::Error; +use bytes::Bytes; +use http_body_util::{BodyExt, Full}; +use hyper::{Request, Response}; +use hyper_util::{client::legacy::Client, rt::TokioExecutor}; +use hyper_util::client::legacy::connect::HttpConnector; + +use super::{ByteStreamBody, Forwarder}; + +/// DirectForwarder forwards requests directly to their target URL +pub struct DirectForwarder { + client: Client, +} + +impl DirectForwarder { + pub fn new() -> Self { + Self { + client: Client::builder(TokioExecutor::new()) + .build::<_, ByteStreamBody>(HttpConnector::new()), + } + } +} + +impl Default for DirectForwarder { + fn default() -> Self { + Self::new() + } +} + +#[async_trait::async_trait] +impl Forwarder for DirectForwarder { + async fn forward(&self, req: Request) -> Result>, Box> { + println!("[DIRECT] Forwarding {} {} to {}", req.method(), req.uri(), req.uri().host().unwrap_or("unknown")); + println!("[DIRECT] Request headers: {:?}", req.headers()); + let response = self.client.request(req).await?; + println!("[DIRECT] Received response: {} from upstream", response.status()); + println!("[DIRECT] Response headers: {:?}", response.headers()); + let (parts, body) = response.into_parts(); + let bytes = body.collect().await?.to_bytes(); + let response = Response::from_parts(parts, Full::new(bytes)); + println!("[DIRECT] Forwarding response to client"); + Ok(response) + } +} diff --git a/src/forwarder/mod.rs b/src/forwarder/mod.rs new file mode 100644 index 0000000..bbe5c22 --- /dev/null +++ b/src/forwarder/mod.rs @@ -0,0 +1,72 @@ +use bytes::Bytes; +use futures::Stream; +use futures_util::StreamExt; +use http_body_util::{BodyExt, Full, StreamBody}; +use hyper::body::{Frame, Incoming}; +use hyper::Request; +use std::error::Error; +use std::pin::Pin; + +/// Trait defining the behavior of a request forwarder +#[async_trait::async_trait] +pub trait Forwarder: Send + Sync { + /// Forward an HTTP request according to the forwarder's strategy + async fn forward(&self, req: Request) -> Result>, Box>; +} + +mod direct; +mod proxy; + +pub use direct::DirectForwarder; +pub use proxy::ProxyForwarder; + +pub type ByteStreamBody = StreamBody, Box>> + Send + 'static>>>; + + +pub fn to_transformed_body( + incoming: Incoming, +) -> ByteStreamBody { + let stream = incoming.into_data_stream().map(|result| { + result + .map(Frame::data) + .map_err(|enc_err| Box::new(enc_err) as Box) + }); + + StreamBody::new( + Box::pin(stream) + as Pin, Box>> + Send>> + ) +} + + +pub fn convert_request_body( + req: hyper::Request, +) -> hyper::Request +where + A: hyper::body::Body + Send + 'static, + A::Data: Into, + A::Error: Error + Send + Sync + 'static, +{ + let (parts, body) = req.into_parts(); + println!("[PROXY] Request body: {:?}", parts); + let body_stream = convert_body(body); + hyper::Request::from_parts(parts, body_stream) +} + +pub fn convert_body(body: A) -> ByteStreamBody +where + A: hyper::body::Body + Send + 'static, + A::Data: Into, + A::Error: Error + Send + Sync + 'static, +{ + let stream = body.into_data_stream().map(|result| { + result + .map(|data| Frame::data(data.into())) + .map_err(|e| Box::new(e) as Box) + }); + StreamBody::new( + Box::pin(stream) + as Pin, Box>> + Send>> + ) +} + diff --git a/src/forwarder/proxy.rs b/src/forwarder/proxy.rs new file mode 100644 index 0000000..f72083b --- /dev/null +++ b/src/forwarder/proxy.rs @@ -0,0 +1,114 @@ +//! Proxy forwarding implementation for HTTP requests + +use bytes::Bytes; +use http::header::HeaderMap; +use http_body_util::{BodyExt, Full}; +use hyper::{Request, Response, Uri}; +use hyper_http_proxy::{Proxy, ProxyConnector, Intercept}; +use hyper_util::{client::legacy::{connect::HttpConnector, Client}, rt::TokioExecutor}; +use std::{error::Error, fmt}; + +use super::{ByteStreamBody, Forwarder}; + +#[derive(Debug)] +pub enum ProxyError { + Configuration(String), +} + +impl fmt::Display for ProxyError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ProxyError::Configuration(msg) => write!(f, "Proxy configuration error: {}", msg), + } + } +} + +impl Error for ProxyError {} + +#[cfg(test)] +mod tests { + use super::*; + use crate::forwarder::convert_request_body; + use bytes::Bytes; + use http_body_util::combinators::BoxBody; + use http_body_util::{BodyExt, Empty}; + use std::convert::Infallible; + + #[tokio::test] + async fn test_proxy_forwarding() { + let proxy = ProxyForwarder::new( + "http://127.0.0.1:8080".parse().unwrap(), + HeaderMap::new() + ); + + // Create an empty body that implements Body trait + let empty_body: BoxBody = Empty::::new().boxed(); + + let request: Request> = Request::builder() + .method("GET") + .uri("http://www.google.com") + .body(empty_body) + .unwrap(); + + let response = proxy.forward(convert_request_body(request)).await.unwrap(); + assert!(response.status().is_success()); + + let body = response.into_body().collect().await.unwrap().to_bytes(); + assert!(!body.is_empty()); + } +} + +pub struct ProxyForwarder { + client: Client, ByteStreamBody>, + proxy: Proxy, + proxy_headers: HeaderMap, +} + + +#[async_trait::async_trait] +impl Forwarder for ProxyForwarder { + async fn forward(&self, mut req: Request) -> Result>, Box> { + println!("[PROXY] Forwarding {} {} via proxy", + req.method(), + req.uri() + ); + + // Add proxy-specific headers if needed for HTTP requests + if req.method() != hyper::Method::CONNECT { + req.headers_mut().extend(self.proxy.headers().clone()); + } + + // Add any additional headers + req.headers_mut().extend(self.proxy_headers.clone()); + + println!("[PROXY] Request URI: {}", req.uri()); + let incoming_response = self.client.request(req).await?; + println!("[PROXY] Received response: {}", incoming_response.status()); + + let (parts, body) = incoming_response.into_parts(); + let bytes = body.collect().await?.to_bytes(); + Ok(Response::from_parts(parts, Full::new(bytes))) + } +} + +impl ProxyForwarder { + pub fn new(proxy_uri: Uri, proxy_headers: HeaderMap, _insecure: bool) -> Self { + let proxy = Proxy::new(Intercept::All, proxy_uri.clone()); + let connector = HttpConnector::new(); + let proxy_connector = ProxyConnector::from_proxy(connector, proxy.clone()) + .expect("Failed to create proxy connector"); + + Self { + client: Client::builder(TokioExecutor::new()) + .pool_idle_timeout(std::time::Duration::from_secs(30)) + .build::<_, ByteStreamBody>(proxy_connector), + proxy, + proxy_headers, + } + } + + // No longer needed as the logic is now in forward() + fn rewrite_request(&self, req: Request) -> Result, ProxyError> { + Ok(req) + } +} diff --git a/src/handler.rs b/src/handler.rs index dd97fd9..aca3de1 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -1,10 +1,12 @@ +use crate::forwarder::{convert_request_body, Forwarder}; +use crate::tunnel::tunnel; use bytes::Bytes; -use http_body_util::{BodyExt, Empty, Full}; +use http_body_util::Full; use hyper::body::Incoming; use hyper::http::response::Builder; use hyper::{Method, StatusCode}; use std::error::Error; -use crate::tunnel::tunnel; +use std::sync::Arc; #[derive(Debug)] pub enum ProxyError { @@ -51,8 +53,17 @@ fn error_response(status: StatusCode) -> Result>, hy pub async fn handle_request( req: hyper::Request, - client: hyper_util::client::legacy::Client, + forwarder: Arc, ) -> Result>, ProxyError> { + println!("[HANDLER] {} {} from {}", + req.method(), + req.uri(), + req.headers().get("x-forwarded-for") + .and_then(|h| h.to_str().ok()) + .unwrap_or("direct") + ); + println!("[HANDLER] Headers: {:?}", req.headers()); + println!("[HANDLER] Version: {:?}", req.version()); if Method::CONNECT == req.method() { if let Some(addr) = req.uri().authority().map(|auth| auth.to_string()) { tokio::task::spawn(async move { @@ -72,12 +83,10 @@ pub async fn handle_request( Ok(error_response(StatusCode::BAD_REQUEST)?) } } else { - match client.request(req).await { - Ok(response) => { - let (parts, body) = response.into_parts(); - let bytes = body.collect().await?.to_bytes(); - Ok(hyper::Response::from_parts(parts, Full::new(bytes))) - }, + + + match forwarder.forward(convert_request_body(req)).await { + Ok(response) => Ok(response), Err(e) => { eprintln!("Error forwarding request: {}", e); Ok(error_response(StatusCode::BAD_GATEWAY)?) @@ -85,3 +94,5 @@ pub async fn handle_request( } } } + + diff --git a/src/main.rs b/src/main.rs index 6a8444d..9f9615d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod logic; mod conditions; mod proxy_types; mod tunnel; +mod forwarder; use rustls::ServerConfig; use std::{ @@ -15,9 +16,11 @@ use tokio_rustls::TlsAcceptor; use clap::Parser; use hyper::server::conn::http1; use hyper::service::service_fn; -use hyper_util::client::legacy::Client; -use hyper_util::client::legacy::connect::HttpConnector; -use hyper_util::rt::{TokioExecutor, TokioIo}; +use hyper_util::rt::TokioIo; + +use forwarder::{Forwarder, DirectForwarder, ProxyForwarder}; +use http::header::HeaderMap; +use hyper::Uri; mod handler; mod config; @@ -44,25 +47,47 @@ struct Args { /// HTTPS proxy listen address #[arg(long, default_value = "127.0.0.1:8443")] https_addr: String, + + /// Upstream proxy to forward requests to + #[arg(long)] + upstream_proxy: Option, + + /// Skip TLS verification when connecting to upstream proxy + #[arg(long)] + upstream_insecure: bool, } async fn run_http_server( addr: SocketAddr, + proxy_uri: Option, + insecure: bool, ) -> Result<(), Box> { let listener = TcpListener::bind(addr).await?; println!("HTTP Listening on http://{}", addr); + let forwarder: Arc = if let Some(proxy_uri) = proxy_uri { + println!("Using upstream proxy: {}", proxy_uri); + let mut headers = HeaderMap::new(); + // Add any custom headers for the upstream proxy if needed + Arc::new(ProxyForwarder::new( + proxy_uri.parse::().expect("Invalid proxy URI"), + headers, + insecure + )) + } else { + Arc::new(DirectForwarder::new()) + }; + loop { let (stream, _) = listener.accept().await?; let io = TokioIo::new(stream); - let client = Client::builder(TokioExecutor::new()) - .build::<_, hyper::body::Incoming>(HttpConnector::new()); + let forwarder = forwarder.clone(); tokio::spawn(async move { if let Err(err) = http1::Builder::new() .serve_connection( io, - service_fn(move |req| handle_request(req, client.clone())), + service_fn(move |req| handle_request(req, forwarder.clone())), ) .with_upgrades() .await @@ -76,16 +101,30 @@ async fn run_http_server( async fn run_https_server( addr: SocketAddr, tls_config: ServerConfig, + proxy_uri: Option, + insecure: bool, ) -> Result<(), Box> { let tls_acceptor = TlsAcceptor::from(Arc::new(tls_config)); let listener = TcpListener::bind(addr).await?; println!("HTTPS Listening on https://{}", addr); + let forwarder: Arc = if let Some(proxy_uri) = proxy_uri { + println!("Using upstream proxy: {}", proxy_uri); + let mut headers = HeaderMap::new(); + // Add any custom headers for the upstream proxy if needed + Arc::new(ProxyForwarder::new( + proxy_uri.parse::().expect("Invalid proxy URI"), + headers, + insecure + )) + } else { + Arc::new(DirectForwarder::new()) + }; + while let Ok((stream, addr)) = listener.accept().await { println!("Accepted connection from {}", addr); let tls_acceptor = tls_acceptor.clone(); - let client = Client::builder(TokioExecutor::new()) - .build::<_, hyper::body::Incoming>(HttpConnector::new()); + let forwarder = forwarder.clone(); tokio::spawn(async move { match tls_acceptor.accept(stream).await { @@ -108,7 +147,7 @@ async fn run_https_server( if let Err(err) = http1::Builder::new() .serve_connection( io, - service_fn(move |req| handle_request(req, client.clone())), + service_fn(move |req| handle_request(req, forwarder.clone())), ) .with_upgrades() .await @@ -147,12 +186,12 @@ async fn main() -> Result<(), Box> { println!(" Using key: {}", args.key); tokio::select! { - result = run_http_server(http_addr) => { + result = run_http_server(http_addr, args.upstream_proxy.clone(), args.upstream_insecure) => { if let Err(e) = result { eprintln!("HTTP server error: {}", e); } } - result = run_https_server(https_addr, tls_config) => { + result = run_https_server(https_addr, tls_config, args.upstream_proxy, args.upstream_insecure) => { if let Err(e) = result { eprintln!("HTTPS server error: {}", e); } diff --git a/src/pac.rs b/src/pac.rs index 210b9e2..0508fc2 100644 --- a/src/pac.rs +++ b/src/pac.rs @@ -1,5 +1,5 @@ -use crate::logic::PacExpression; use crate::conditions::{parse_condition, PacCondition}; +use crate::logic::PacExpression; use crate::proxy_types::ProxyType; use boa_engine::ast::expression::literal::Literal; use boa_engine::ast::statement::{If, Return}; @@ -179,12 +179,12 @@ mod to_js_tests { #[cfg(test)] mod pac_files_test { - use boa_engine::{js_string, Context, JsString, JsValue, NativeFunction}; - use boa_engine::object::ObjectInitializer; - use boa_engine::property::Attribute; use super::*; use crate::conditions::{PacCondition, Protocol}; use crate::logic::ToJs; + use boa_engine::ast::scope::Scope; + use boa_engine::{Context, JsString, JsValue, NativeFunction}; + use boa_parser::{Parser, Source}; #[test] fn test_company_pac_file() { diff --git a/src/tunnel.rs b/src/tunnel.rs index 80fd831..6fcee87 100644 --- a/src/tunnel.rs +++ b/src/tunnel.rs @@ -1,5 +1,5 @@ use hyper::upgrade::Upgraded; -use tokio::io::{copy_bidirectional, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf}; +use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf}; use tokio::net::TcpStream; use std::pin::Pin; @@ -113,7 +113,7 @@ pub fn extract_tls_info(data: &[u8]) -> Option { pub async fn tunnel(upgraded: Upgraded, addr: String) -> std::io::Result<()> { let upstream = TcpStream::connect(&addr).await?; - let mut io = UpgradedIo(upgraded); + let io = UpgradedIo(upgraded); let (mut client_read, mut client_write) = tokio::io::split(io); let (mut upstream_read, mut upstream_write) = upstream.into_split();