diff --git a/README.md b/README.md index 7fca97c..533f98f 100644 --- a/README.md +++ b/README.md @@ -12,28 +12,7 @@ TODO: - Remove panics - Creating trees of flowgate -## Config - -Default `conf.yml`: -```yml -http_host: localhost:80 # Http server host -https_host: localhost:443 # Https server host - -threadpool_size: 10 # Threadpool size (count of threads that accept requests) (optional, default - 10) -connection_timeout: 10 # Read and write timeout of connections in seconds (optional, default - 10) -incoming_ip_forwarding: none # Read IP forwarding on incoming connections (optional, default - none) - -sites: - - domain: localhost # Site domain (use wildcard matching) - host: localhost:8080 # Http server host - ip_forwarding: simple # IP forwarding method type (optional, default - header) - enable_keep_alive: true # Enable keep-alive connections (optional, default - true) - support_keep_alive: true # Does server supports keep-alive connections (optional, default - true) - # ssl_cert: "/path/to/public/certificate.txt" # Ssl public certificate file (optional) - # ssl_key: "/path/to/private/key.txt" # Ssl private key file (optional) -``` - -### IP forwaring types +## IP forwarding types - None (`none`):\ Do nothing diff --git a/conf.yml b/conf.yml index 1928a7b..8cf6f65 100644 --- a/conf.yml +++ b/conf.yml @@ -14,4 +14,5 @@ sites: enable_keep_alive: true # Enable keep-alive connections (optional, default - true) support_keep_alive: true # Does server supports keep-alive connections (optional, default - true) # ssl_cert: "/path/to/public/certificate.txt" # Ssl public certificate file (optional) - # ssl_key: "/path/to/private/key.txt" # Ssl private key file (optional) \ No newline at end of file + # ssl_key: "/path/to/private/key.txt" # Ssl private key file (optional) + replace_host: "pansangg.github.io" # Replace Host header in requests to server (optional) \ No newline at end of file diff --git a/src/flowgate/config.rs b/src/flowgate/config.rs index 1fabffd..541ef05 100644 --- a/src/flowgate/config.rs +++ b/src/flowgate/config.rs @@ -12,7 +12,8 @@ pub struct SiteConfig { pub ssl: Option, pub enable_keep_alive: bool, pub support_keep_alive: bool, - pub ip_forwarding: IpForwarding + pub ip_forwarding: IpForwarding, + pub replace_host: Option } impl SiteConfig { @@ -105,6 +106,8 @@ impl Config { .map(|o| o.as_str()).flatten() .map(|o| IpForwarding::from_name(o)).flatten() .unwrap_or(IpForwarding::Header("X-Real-IP".to_string())), + replace_host: s.get("replace_host") + .map(|o| o.as_str()).flatten().map(|o| o.to_string()), }; sites.push(site); diff --git a/src/flowgate/server.rs b/src/flowgate/server.rs index f310300..2fa8b86 100644 --- a/src/flowgate/server.rs +++ b/src/flowgate/server.rs @@ -186,19 +186,19 @@ impl FlowgateServer { addr: SocketAddr, https: bool ) -> Option<()> { - let mut connected = Self::read_request(config.clone(), stream, addr, https, None)?; + let mut conn = Self::read_request(config.clone(), stream, addr, https, None)?; - if connected.2 && connected.1.enable_keep_alive { + if conn.2 && conn.1.enable_keep_alive { loop { - if !connected.1.support_keep_alive { - connected.0.close(); - connected.0 = connected.1.connect()?; + if !conn.1.support_keep_alive { + conn.0.close(); + conn.0 = conn.1.connect()?; } - connected = Self::read_request(config.clone(), stream, addr, https, Some(connected))?; + conn = Self::read_request(config.clone(), stream, addr, https, Some(conn))?; } } - connected.0.close(); + conn.0.close(); stream.close(); Some(()) @@ -209,7 +209,7 @@ impl FlowgateServer { stream: &'a mut (impl Read + Write + Closeable), addr: SocketAddr, https: bool, - connected: Option<(TcpStream, SiteConfig, bool, String)> + conn: Option<(TcpStream, SiteConfig, bool, String)> ) -> Option<(TcpStream, SiteConfig, bool, String)> { let mut addr = addr; @@ -275,8 +275,6 @@ impl FlowgateServer { head.truncate(head.len() - 4); } - // println!("read client head"); - if head.is_empty() { return None; } let head_str = String::from_utf8(head.clone()).ok()?; @@ -298,7 +296,7 @@ impl FlowgateServer { } } - let mut connected: (TcpStream, SiteConfig, bool, String) = if connected.is_none() { + let mut conn: (TcpStream, SiteConfig, bool, String) = if conn.is_none() { let mut host = String::new(); let mut keep_alive = false; @@ -314,7 +312,7 @@ impl FlowgateServer { (site.connect()?, site, keep_alive, host) } else { - connected? + conn? }; let content_length = headers @@ -327,7 +325,31 @@ impl FlowgateServer { let mut reqbuf: Vec = Vec::new(); - match &connected.1.ip_forwarding { + if let Some(replace_host) = conn.1.replace_host.clone() { + let mut new_head = Vec::new(); + let mut is_status = true; + + for line in head_str.split("\r\n") { + if is_status { + new_head.append(&mut line.as_bytes().to_vec()); + is_status = false; + } else { + new_head.append(&mut b"\r\n".to_vec()); + let (key, _) = line.split_once(": ")?; + if key.to_lowercase() == "host" { + new_head.append(&mut key.as_bytes().to_vec()); + new_head.append(&mut b": ".to_vec()); + new_head.append(&mut replace_host.as_bytes().to_vec()); + } else { + new_head.append(&mut line.as_bytes().to_vec()); + } + } + } + + head = new_head; + } + + match &conn.1.ip_forwarding { IpForwarding::Header(header) => { reqbuf.append(&mut status.to_string().as_bytes().to_vec()); reqbuf.append(&mut b"\r\n".to_vec()); @@ -362,12 +384,13 @@ impl FlowgateServer { reqbuf.append(&mut head.clone()); reqbuf.append(&mut b"\r\n\r\n".to_vec()); }, - IpForwarding::None => { } + IpForwarding::None => { + reqbuf.append(&mut head.clone()); + reqbuf.append(&mut b"\r\n\r\n".to_vec()); + } } - connected.0.write_all(&reqbuf).ok()?; - - // println!("wrote client head to server"); + conn.0.write_all(&reqbuf).ok()?; if content_length > 0 { let mut read = 0usize; @@ -376,22 +399,20 @@ impl FlowgateServer { if size == 0 { break } read += size; buf.truncate(size); - connected.0.write_all(&buf).ok()?; + conn.0.write_all(&buf).ok()?; buf = vec![0; 4096]; if read == content_length { break } } } - // println!("wrote client body to server"); - - if connected.1.support_keep_alive { + if conn.1.support_keep_alive { let mut head = Vec::new(); { let mut buf = [0; 1]; let mut counter = 0; - while let Ok(1) = connected.0.read(&mut buf) { + while let Ok(1) = conn.0.read(&mut buf) { let byte = buf[0]; head.push(byte); @@ -427,7 +448,7 @@ impl FlowgateServer { if content_length > 0 { let mut read = 0usize; let mut buf = vec![0; 4096]; - while let Ok(size) = connected.0.read(&mut buf) { + while let Ok(size) = conn.0.read(&mut buf) { if size == 0 { break } read += size; buf.truncate(size); @@ -438,14 +459,12 @@ impl FlowgateServer { } } else { let mut buf = Vec::new(); - connected.0.read_to_end(&mut buf).ok()?; + conn.0.read_to_end(&mut buf).ok()?; stream.write_all(&buf).ok()?; } - // println!("wrote server response to client"); + info!("{addr} > {} {}://{}{}", status_seq[0], if https { "https" } else { "http" }, conn.3, status_seq[1]); - info!("{addr} > {} {}://{}{}", status_seq[0], if https { "https" } else { "http" }, connected.3, status_seq[1]); - - Some(connected) + Some(conn) } } \ No newline at end of file diff --git a/src/flowgate/websocket.rs b/src/flowgate/websocket.rs index a835497..cc3161c 100644 --- a/src/flowgate/websocket.rs +++ b/src/flowgate/websocket.rs @@ -23,6 +23,7 @@ fn on_message(config: Arc>, data: Value) -> Option<()> { enable_keep_alive: data.get("enable_keep_alive")?.as_bool()?, support_keep_alive: data.get("support_keep_alive")?.as_bool()?, ip_forwarding: IpForwarding::from_name(data.get("ip_forwarding")?.as_str()?)?, + replace_host: data.get("replace_host").map(|o| o.as_str()).flatten().map(|o| o.to_string()), ssl: None }); }