1#[cfg(all(test, not(target_arch = "wasm32")))]
2pub mod tests;
3#[cfg(all(test, not(target_arch = "wasm32")))]
4mod example;
5
6#[cfg(not(target_arch = "wasm32"))]
12use std::io::prelude::*;
13#[cfg(not(target_arch = "wasm32"))]
14use std::borrow::Borrow;
15#[cfg(not(target_arch = "wasm32"))]
16use std::net::{IpAddr, SocketAddr, TcpListener};
17#[cfg(not(target_arch = "wasm32"))]
18use std::str::FromStr;
19#[cfg(not(target_arch = "wasm32"))]
20use std::time::Duration;
21
22#[cfg(not(target_arch = "wasm32"))]
23use crate::request::{METHOD, Request};
24#[cfg(not(target_arch = "wasm32"))]
25use crate::response::{Response, STATUS_CODE_REASON_PHRASE};
26#[cfg(not(target_arch = "wasm32"))]
27use crate::app::App;
28#[cfg(not(target_arch = "wasm32"))]
29use crate::application::Application;
30#[cfg(not(target_arch = "wasm32"))]
31use crate::entry_point::{bootstrap, get_ip_port_thread_count, get_request_allocation_size, set_default_values};
32#[cfg(not(target_arch = "wasm32"))]
33use crate::header::Header;
34#[cfg(not(target_arch = "wasm32"))]
35use crate::log::Log;
36#[cfg(not(target_arch = "wasm32"))]
37use crate::mime_type::MimeType;
38#[cfg(not(target_arch = "wasm32"))]
39use crate::range::{ContentRange, Range};
40#[cfg(not(target_arch = "wasm32"))]
41use crate::symbol::SYMBOL;
42#[cfg(not(target_arch = "wasm32"))]
43use crate::thread_pool::ThreadPool;
44
45#[cfg(not(target_arch = "wasm32"))]
46pub struct Server {}
47#[cfg(not(target_arch = "wasm32"))]
48impl Server {
49 pub fn process_request(mut stream: impl Read + Write + Unpin, peer_addr: SocketAddr) -> Vec<u8> {
50 let request_allocation_size = get_request_allocation_size();
51 let mut buffer = vec![0; request_allocation_size as usize];
52 let boxed_read = stream.read(&mut buffer);
53 if boxed_read.is_err() {
54 let message = boxed_read.err().unwrap().to_string();
55 eprintln!("unable to read TCP stream {}", &message);
56
57 let raw_response = Server::bad_request_response(message);
58 let boxed_stream = stream.write(raw_response.borrow());
59 if boxed_stream.is_ok() {
60 stream.flush().unwrap();
61 };
62 return raw_response;
63 }
64
65 boxed_read.unwrap();
66 let request : &[u8] = &buffer;
67
68 let boxed_request = Request::parse_request(request);
73 if boxed_request.is_err() {
74 let message = boxed_request.err().unwrap();
75 eprintln!("unable to parse request: {}", &message);
76
77 let raw_response = Server::bad_request_response(message);
78 let boxed_stream = stream.write(raw_response.borrow());
79 if boxed_stream.is_ok() {
80 stream.flush().unwrap();
81 };
82 return raw_response;
83 }
84
85
86 let request: Request = boxed_request.unwrap();
87 let (response, request) = App::handle_request(request);
88
89
90 let log_request_response = Log::combined(&request, &response, &peer_addr);
91 println!("{}", log_request_response);
92 let raw_response = Response::generate_response(response, request);
93
94 let boxed_stream = stream.write(raw_response.borrow());
95 if boxed_stream.is_ok() {
96 stream.flush().unwrap();
97 };
98
99 raw_response
100 }
101
102 pub fn bad_request_response(message: String) -> Vec<u8> {
103 let error_request = Request {
104 method: METHOD.get.to_string(),
105 request_uri: "".to_string(),
106 http_version: "".to_string(),
107 headers: vec![],
108 body: vec![],
109 };
110
111 let size = message.chars().count() as u64;
112 let content_range = ContentRange {
113 unit: Range::BYTES.to_string(),
114 range: Range { start: 0, end: size },
115 size: size.to_string(),
116 body: Vec::from(message.as_bytes()),
117 content_type: MimeType::TEXT_PLAIN.to_string(),
118 };
119
120 let header_list = Header::get_header_list(&error_request);
121 let error_response: Response = Response::get_response(
122 STATUS_CODE_REASON_PHRASE.n400_bad_request,
123 Some(header_list),
124 Some(vec![content_range])
125 );
126
127 let response = Response::generate_response(error_response, error_request);
128 return response;
129 }
130
131 pub fn payload_too_large_response(message: String) -> Vec<u8> {
137 let error_request = Request {
138 method: METHOD.get.to_string(),
139 request_uri: "".to_string(),
140 http_version: "".to_string(),
141 headers: vec![],
142 body: vec![],
143 };
144
145 let size = message.chars().count() as u64;
146 let content_range = ContentRange {
147 unit: Range::BYTES.to_string(),
148 range: Range { start: 0, end: size },
149 size: size.to_string(),
150 body: Vec::from(message.as_bytes()),
151 content_type: MimeType::TEXT_PLAIN.to_string(),
152 };
153
154 let mut header_list = Header::get_header_list(&error_request);
155 header_list.push(Header { name: Header::_CONNECTION.to_string(), value: "close".to_string() });
156 let error_response: Response = Response::get_response(
157 STATUS_CODE_REASON_PHRASE.n413_payload_too_large,
158 Some(header_list),
159 Some(vec![content_range])
160 );
161
162 Response::generate_response(error_response, error_request)
163 }
164
165 pub fn continue_response() -> Vec<u8> {
171 let dummy_request = Request {
172 method: METHOD.get.to_string(),
173 request_uri: "".to_string(),
174 http_version: "".to_string(),
175 headers: vec![],
176 body: vec![],
177 };
178 let response = Response::get_response(STATUS_CODE_REASON_PHRASE.n100_continue, None, None);
179 Response::generate_response(response, dummy_request)
180 }
181
182 pub fn expectation_failed_response(message: String) -> Vec<u8> {
187 let error_request = Request {
188 method: METHOD.get.to_string(),
189 request_uri: "".to_string(),
190 http_version: "".to_string(),
191 headers: vec![],
192 body: vec![],
193 };
194
195 let size = message.chars().count() as u64;
196 let content_range = ContentRange {
197 unit: Range::BYTES.to_string(),
198 range: Range { start: 0, end: size },
199 size: size.to_string(),
200 body: Vec::from(message.as_bytes()),
201 content_type: MimeType::TEXT_PLAIN.to_string(),
202 };
203
204 let mut header_list = Header::get_header_list(&error_request);
205 header_list.push(Header { name: Header::_CONNECTION.to_string(), value: "close".to_string() });
206 let error_response: Response = Response::get_response(
207 STATUS_CODE_REASON_PHRASE.n417_expectation_failed,
208 Some(header_list),
209 Some(vec![content_range])
210 );
211
212 Response::generate_response(error_response, error_request)
213 }
214
215 pub fn process(mut stream: impl Read + Write + Unpin,
216 connection: ConnectionInfo,
217 app: impl Application) -> Result<(), String> {
218 use crate::http::VERSION;
219
220 let request_allocation_size = connection.request_size;
221 let client = connection.client.clone();
222 let client_addr = SocketAddr::new(IpAddr::from_str(client.ip.as_str()).unwrap(), client.port as u16);
223
224 let max_body_size = crate::entry_point::get_max_body_size();
225
226 loop {
227 let mut buffer = vec![0; request_allocation_size as usize];
228 let boxed_read = stream.read(&mut buffer);
229 let n = match boxed_read {
230 Err(_) => break,
232 Ok(0) => break,
233 Ok(n) => n,
234 };
235
236 let mut request = match Request::parse(&buffer[..n]) {
239 Ok(r) => r,
240 Err(message) => {
241 let raw_response = Server::bad_request_response(message.clone());
242 let boxed_stream = stream.write(raw_response.borrow());
243 if boxed_stream.is_ok() { stream.flush().unwrap(); }
244 return Err(message);
245 }
246 };
247
248 let expects_continue = match request.get_header(Header::_EXPECT.to_string()) {
252 Some(h) if h.value.trim().eq_ignore_ascii_case("100-continue") => true,
253 Some(h) => {
254 let raw_response = Server::expectation_failed_response(format!(
255 "417 Expectation Failed: unsupported Expect value '{}'", h.value.trim()
256 ));
257 let boxed_stream = stream.write(raw_response.borrow());
258 if boxed_stream.is_ok() { stream.flush().unwrap(); }
259 break;
260 }
261 None => false,
262 };
263
264 if let Some(declared_len) = request
268 .get_header(Header::_CONTENT_LENGTH.to_string())
269 .and_then(|h| h.value.trim().parse::<u64>().ok())
270 {
271 if max_body_size > 0 && declared_len > max_body_size {
272 let raw_response = Server::payload_too_large_response(format!(
273 "413 Payload Too Large: declared Content-Length {} exceeds the {} byte limit",
274 declared_len, max_body_size
275 ));
276 let boxed_stream = stream.write(raw_response.borrow());
277 if boxed_stream.is_ok() { stream.flush().unwrap(); }
278 break;
279 }
280
281 if expects_continue {
284 let raw_response = Server::continue_response();
285 match stream.write(raw_response.borrow()) {
286 Ok(_) => stream.flush().unwrap(),
287 Err(_) => break,
288 }
289 }
290
291 while (request.body.len() as u64) < declared_len {
292 let mut more = vec![0u8; request_allocation_size as usize];
293 match stream.read(&mut more) {
294 Ok(0) | Err(_) => break, Ok(k) => request.body.extend_from_slice(&more[..k]),
296 }
297 }
298 }
299
300 let keep_alive = {
301 let conn_hdr = request.get_header(Header::_CONNECTION.to_string());
302 match conn_hdr {
303 Some(h) => h.value.to_lowercase() != "close",
304 None => request.http_version == VERSION.http_1_1,
305 }
306 };
307
308 let mut response = match app.execute(&request, &connection) {
309 Ok(r) => r,
310 Err(message) => {
311 let raw_response = Server::bad_request_response(message.clone());
312 let boxed_stream = stream.write(raw_response.borrow());
313 if boxed_stream.is_ok() { stream.flush().unwrap(); }
314 return Err(message);
315 }
316 };
317
318 crate::metrics::record_request();
319 crate::compression::apply_gzip(&request, &mut response);
320
321 response.headers.push(Header {
322 name: Header::_CONNECTION.to_string(),
323 value: if keep_alive { "keep-alive".to_string() } else { "close".to_string() },
324 });
325
326 Log::log_access(&request, &response, &client_addr);
327
328 if let Some(reader) = response.stream_pipe.take() {
329 if let Err(e) = Server::pipe_stream(&mut stream, response, request, reader) {
330 return Err(e);
331 }
332 } else if let Some(ref filepath) = response.stream_file.clone() {
333 if let Err(e) = Server::write_chunked_file(&mut stream, response, request, filepath) {
334 return Err(e);
335 }
336 } else {
337 let raw_response = Response::generate_response(response, request);
338 if let Err(e) = stream.write(raw_response.borrow()) {
339 return Err(e.to_string());
340 }
341 stream.flush().unwrap();
342 }
343
344 if !keep_alive { break; }
345 }
346
347 Ok(())
348 }
349
350 pub(crate) fn write_chunked_file(
353 stream: &mut impl Write,
354 mut response: Response,
355 request: Request,
356 filepath: &str,
357 ) -> Result<(), String> {
358 use std::fs::File;
359 use std::io::Read as _;
360
361 response.headers.push(Header {
362 name: Header::_TRANSFER_ENCODING.to_string(),
363 value: "chunked".to_string(),
364 });
365
366 let status = [
368 response.http_version.clone(),
369 response.status_code.to_string(),
370 response.reason_phrase.clone(),
371 ].join(SYMBOL.whitespace);
372
373 let mut headers_str = SYMBOL.new_line_carriage_return.to_string();
374 for header in &response.headers {
375 headers_str.push_str(&header.name);
376 headers_str.push_str(Header::NAME_VALUE_SEPARATOR);
377 headers_str.push_str(&header.value);
378 headers_str.push_str(SYMBOL.new_line_carriage_return);
379 }
380 let head = format!("{}{}{}", status, headers_str, SYMBOL.new_line_carriage_return);
381
382 stream.write_all(head.as_bytes()).map_err(|e| e.to_string())?;
383
384 if request.method != METHOD.head && request.method != METHOD.options {
385 let mut file = File::open(filepath).map_err(|e| e.to_string())?;
386 let mut buf = vec![0u8; 65536];
387 loop {
388 let n = file.read(&mut buf).map_err(|e| e.to_string())?;
389 if n == 0 { break; }
390 stream.write_all(format!("{:x}\r\n", n).as_bytes()).map_err(|e| e.to_string())?;
392 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
393 stream.write_all(b"\r\n").map_err(|e| e.to_string())?;
394 }
395 stream.write_all(b"0\r\n\r\n").map_err(|e| e.to_string())?;
397 }
398
399 stream.flush().map_err(|e| e.to_string())
400 }
401
402 pub(crate) fn pipe_stream(
410 stream: &mut impl Write,
411 mut response: Response,
412 request: Request,
413 mut reader: Box<dyn std::io::Read + Send>,
414 ) -> Result<(), String> {
415 let backend_is_chunked = response.headers.iter().any(|h| {
419 h.name.eq_ignore_ascii_case("transfer-encoding")
420 && h.value.to_lowercase().contains("chunked")
421 });
422
423 response.headers.retain(|h| !h.name.eq_ignore_ascii_case("content-length"));
424 if !backend_is_chunked {
425 response.headers.push(Header {
426 name: Header::_TRANSFER_ENCODING.to_string(),
427 value: "chunked".to_string(),
428 });
429 }
430
431 let status = [
432 response.http_version.clone(),
433 response.status_code.to_string(),
434 response.reason_phrase.clone(),
435 ].join(SYMBOL.whitespace);
436
437 let mut head = format!("{}\r\n", status);
438 for header in &response.headers {
439 head.push_str(&header.name);
440 head.push_str(Header::NAME_VALUE_SEPARATOR);
441 head.push_str(&header.value);
442 head.push_str(SYMBOL.new_line_carriage_return);
443 }
444 head.push_str(SYMBOL.new_line_carriage_return);
445 stream.write_all(head.as_bytes()).map_err(|e| e.to_string())?;
446
447 if request.method != METHOD.head && request.method != METHOD.options {
448 let mut buf = [0u8; 8192];
449 if backend_is_chunked {
450 loop {
453 match reader.read(&mut buf) {
454 Ok(0) | Err(_) => break,
455 Ok(n) => {
456 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
457 stream.flush().map_err(|e| e.to_string())?;
458 }
459 }
460 }
461 } else {
462 loop {
466 match reader.read(&mut buf) {
467 Ok(0) | Err(_) => break,
468 Ok(n) => {
469 stream
470 .write_all(format!("{:x}\r\n", n).as_bytes())
471 .map_err(|e| e.to_string())?;
472 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
473 stream.write_all(b"\r\n").map_err(|e| e.to_string())?;
474 stream.flush().map_err(|e| e.to_string())?;
475 }
476 }
477 }
478 stream.write_all(b"0\r\n\r\n").map_err(|e| e.to_string())?;
479 }
480 }
481
482 stream.flush().map_err(|e| e.to_string())
483 }
484
485 pub fn setup() -> Result<(TcpListener, ThreadPool), String> {
488 let info = Log::info("Rust Web Server");
489 println!("{}", info);
490
491 let usage_info = Log::usage_information();
492 println!("{}", usage_info);
493
494
495 println!("RWS Configuration Start: \n");
496
497 set_default_values();
498 bootstrap();
499
500 #[cfg(feature = "secrets")]
501 crate::secrets::resolve_env_vars().map_err(|e| e.to_string())?;
502
503 println!("\nRWS Configuration End\n\n");
504
505
506 let (ip, port, thread_count) = get_ip_port_thread_count();
507
508
509 let mut ip_readable = ip.to_string();
510
511 if ip.contains(":") {
512 ip_readable = [SYMBOL.opening_square_bracket, &ip, SYMBOL.closing_square_bracket].join("");
513 }
514
515 let bind_addr = [ip_readable, SYMBOL.colon.to_string(), port.to_string()].join(SYMBOL.empty_string);
516
517 #[cfg(feature = "http2")]
518 let protocol = {
519 let cert = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE).unwrap_or_default();
520 if cert.is_empty() { "http" } else { "https" }
521 };
522 #[cfg(not(feature = "http2"))]
523 let protocol = "http";
524
525 println!("Setting up {}://{}...", protocol, &bind_addr);
526
527 let boxed_listener = TcpListener::bind(&bind_addr);
528 if boxed_listener.is_err() {
529 let message = format!("unable to set up TCP listener: {}", boxed_listener.err().unwrap());
530 return Err(message);
531 }
532
533 let listener = boxed_listener.unwrap();
534 let pool = ThreadPool::new(thread_count as usize);
535
536
537 let server_url_thread_count = Log::server_url_thread_count(protocol, &bind_addr, thread_count);
538 println!("{}", server_url_thread_count);
539
540 Ok((listener, pool))
541 }
542
543 pub fn run(listener: TcpListener,
551 pool: ThreadPool,
552 app: impl Application + Send + 'static + Clone) {
553 #[cfg(feature = "http1")]
554 {
555 use std::sync::Arc;
556 use std::sync::atomic::{AtomicBool, Ordering};
557
558 let shutdown = Arc::new(AtomicBool::new(false));
559 let s = shutdown.clone();
560 if let Err(e) = ctrlc::set_handler(move || {
561 s.store(true, Ordering::SeqCst);
562 }) {
563 eprintln!("unable to install signal handler: {}", e);
564 }
565 crate::config_reload::install_sighup_handler();
566 if let Err(e) = listener.set_nonblocking(true) {
567 eprintln!("unable to set non-blocking listener: {}", e);
568 }
569
570 loop {
571 if shutdown.load(Ordering::SeqCst) {
572 break;
573 }
574 if crate::config_reload::RELOAD_REQUESTED
575 .compare_exchange(true, false, Ordering::SeqCst, Ordering::Relaxed)
576 .is_ok()
577 {
578 crate::config_reload::reload();
579 }
580 match listener.accept() {
581 Ok((stream, peer_addr)) => {
582 Server::dispatch_connection(stream, peer_addr, &pool, app.clone());
583 }
584 Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
585 std::thread::sleep(Duration::from_millis(10));
586 }
587 Err(e) => {
588 eprintln!("accept error: {}", e);
589 break;
590 }
591 }
592 }
593
594 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
595 println!("Shutting down — waiting for in-flight connections to finish");
596 pool.join();
597 println!("Server stopped");
598 }
599
600 #[cfg(not(feature = "http1"))]
601 {
602 for boxed_stream in listener.incoming() {
603 match boxed_stream {
604 Err(e) => {
605 eprintln!("unable to get TCP stream: {}", e);
606 return;
607 }
608 Ok(stream) => {
609 let peer_addr = match stream.peer_addr() {
610 Ok(a) => a,
611 Err(e) => {
612 eprintln!("unable to read peer addr: {}", e);
613 return;
614 }
615 };
616 Server::dispatch_connection(stream, peer_addr, &pool, app.clone());
617 }
618 }
619 }
620 }
621 }
622
623 fn dispatch_connection(
624 stream: std::net::TcpStream,
625 peer_addr: std::net::SocketAddr,
626 pool: &ThreadPool,
627 app: impl Application + Send + 'static + Clone,
628 ) {
629 print!("Connection established, ");
630 if let Ok(local) = stream.local_addr() {
631 print!("local addr: {}", local);
632 }
633 println!(", peer addr: {}", peer_addr);
634
635 let (server_ip, server_port, _thread_count) = get_ip_port_thread_count();
636 let connection = ConnectionInfo {
637 client: Address {
638 ip: peer_addr.ip().to_string(),
639 port: peer_addr.port() as i32,
640 },
641 server: Address {
642 ip: server_ip,
643 port: server_port,
644 },
645 request_size: get_request_allocation_size(),
646 sni_hostname: None,
647 };
648
649 if let Err(e) = stream.set_read_timeout(Some(Duration::from_secs(30))) {
650 eprintln!("failed to set read timeout: {}", e);
651 }
652
653 pool.execute(move || {
654 crate::metrics::connection_open();
655 let result = Server::process(stream, connection, app);
656 crate::metrics::connection_close();
657 if let Err(msg) = result {
658 crate::metrics::record_error();
659 eprintln!("{}", msg);
660 }
661 });
662 }
663
664}
665
666#[derive(Clone)]
668pub struct ConnectionInfo {
669 pub client: Address,
671 pub server: Address,
673 pub request_size: i64,
675 pub sni_hostname: Option<String>,
678}
679
680#[derive(Clone)]
682pub struct Address {
683 pub ip: String,
684 pub port: i32
685}
686
687impl ConnectionInfo {
688 pub fn peer_addr(&self) -> Option<std::net::SocketAddr> {
691 self.client.to_socket_addr()
692 }
693}
694
695impl Address {
696 pub fn to_socket_addr(&self) -> Option<std::net::SocketAddr> {
699 let ip: std::net::IpAddr = self.ip.parse().ok()?;
700 let port = u16::try_from(self.port).ok()?;
701 Some(std::net::SocketAddr::new(ip, port))
702 }
703}
704
705#[cfg(feature = "http2")]
708async fn sigterm() {
709 #[cfg(unix)]
710 {
711 if let Ok(mut s) = tokio::signal::unix::signal(
712 tokio::signal::unix::SignalKind::terminate()
713 ) {
714 s.recv().await;
715 } else {
716 std::future::pending::<()>().await
717 }
718 }
719 #[cfg(not(unix))]
720 std::future::pending::<()>().await
721}
722
723#[cfg(feature = "http2")]
725async fn sighup() {
726 #[cfg(unix)]
727 {
728 if let Ok(mut s) = tokio::signal::unix::signal(
729 tokio::signal::unix::SignalKind::hangup()
730 ) {
731 s.recv().await;
732 } else {
733 std::future::pending::<()>().await
734 }
735 }
736 #[cfg(not(unix))]
737 std::future::pending::<()>().await
738}
739
740#[cfg(feature = "http2")]
747pub(crate) async fn bind_all_families(ip: &str, port: u16) -> Result<Vec<tokio::net::TcpListener>, String> {
748 use tokio::net::TcpListener;
749 if ip != "0.0.0.0" {
750 let addr = if ip.contains(':') { format!("[{ip}]:{port}") } else { format!("{ip}:{port}") };
751 return TcpListener::bind(&addr).await.map(|l| vec![l]).map_err(|e| format!("{addr}: {e}"));
752 }
753 let mut listeners = Vec::new();
754 let mut errors = Vec::new();
755 for addr in [format!("[::]:{port}"), format!("0.0.0.0:{port}")] {
756 match TcpListener::bind(&addr).await {
757 Ok(l) => listeners.push(l),
758 Err(e) => errors.push(format!("{addr}: {e}")),
759 }
760 }
761 if listeners.is_empty() {
762 return Err(errors.join("; "));
763 }
764 Ok(listeners)
765}
766
767#[cfg(feature = "http2")]
768impl Server {
769 pub async fn run_tls(
770 listener: TcpListener,
771 pool: ThreadPool,
772 app: impl Application + Send + 'static + Clone,
773 ) {
774 use crate::tls::create_tls_acceptor_from_vhosts;
775 use crate::h2_handler;
776
777 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
778 .unwrap_or_default();
779 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
780 .unwrap_or_default();
781
782 if cert_path.is_empty() || key_path.is_empty() {
783 println!("No TLS certificate configured — serving plain HTTP/1.1.");
784 tokio::task::block_in_place(|| Server::run(listener, pool, app));
785 return;
786 }
787
788 let vhosts = crate::entry_point::get_virtual_hosts();
789 let mut tls_acceptor = match create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
790 Ok(a) => a,
791 Err(e) => {
792 eprintln!("TLS setup failed: {}", e);
793 return;
794 }
795 };
796
797 listener
798 .set_nonblocking(true)
799 .expect("failed to set TCP listener to non-blocking");
800 let tokio_listener = tokio::net::TcpListener::from_std(listener)
801 .expect("failed to convert TCP listener to tokio");
802
803 println!("Listening for TLS connections (HTTP/1.1 + HTTP/2)...");
804
805 loop {
806 tokio::select! {
807 result = tokio_listener.accept() => {
808 match result {
809 Ok((tcp_stream, peer_addr)) => {
810 let acceptor = tls_acceptor.clone();
811 let app = app.clone();
812 tokio::spawn(async move {
813 match acceptor.accept(tcp_stream).await {
814 Ok(tls_stream) => {
815 let server_conn = tls_stream.get_ref().1;
816 let sni = server_conn.server_name().map(|s| s.to_string());
817 let protocol = server_conn
818 .alpn_protocol()
819 .map(|p| p.to_vec());
820
821 match protocol.as_deref() {
822 Some(b"h2") => {
823 if let Err(e) =
824 h2_handler::handle_connection(tls_stream, peer_addr, sni, app)
825 .await
826 {
827 eprintln!("H2 connection error: {}", e);
828 }
829 }
830 _ => {
831 if let Err(e) =
832 Server::process_h1_tls(tls_stream, peer_addr, sni, app).await
833 {
834 eprintln!("H1 TLS error: {}", e);
835 }
836 }
837 }
838 }
839 Err(e) => eprintln!("TLS handshake failed: {}", e),
840 }
841 });
842 }
843 Err(e) => eprintln!("TCP accept error: {}", e),
844 }
845 }
846 _ = tokio::signal::ctrl_c() => {
847 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
848 println!("\nShutting down gracefully (SIGINT).");
849 break;
850 }
851 _ = sigterm() => {
852 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
853 println!("\nShutting down gracefully (SIGTERM).");
854 break;
855 }
856 _ = sighup() => {
857 crate::config_reload::reload();
858 let vhosts = crate::entry_point::get_virtual_hosts();
859 if let Ok(new_acceptor) = create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
860 tls_acceptor = new_acceptor;
861 println!("[TLS] Certificates reloaded ({} virtual hosts).", vhosts.len());
862 }
863 }
864 }
865 }
866 }
867
868 pub async fn run_redirect() {
872 use std::env;
873
874 let cert_path = env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
875 .unwrap_or_default();
876 if cert_path.is_empty() {
877 return;
878 }
879
880 let redirect_port_str = env::var(crate::entry_point::Config::RWS_CONFIG_HTTP_REDIRECT_PORT)
881 .unwrap_or_default();
882 if redirect_port_str.is_empty() {
883 return;
884 }
885
886 let redirect_port: u16 = match redirect_port_str.parse() {
887 Ok(p) => p,
888 Err(_) => {
889 eprintln!("Invalid RWS_CONFIG_HTTP_REDIRECT_PORT: {}", redirect_port_str);
890 return;
891 }
892 };
893
894 let (server_ip, server_port, _) = get_ip_port_thread_count();
895 let listeners = match bind_all_families(&server_ip, redirect_port).await {
896 Ok(l) => l,
897 Err(e) => {
898 eprintln!("HTTP redirect listener error on port {}: {}", redirect_port, e);
899 return;
900 }
901 };
902
903 println!("HTTP→HTTPS redirect listening on http://{}:{}", server_ip, redirect_port);
904 #[cfg(feature = "acme")]
905 crate::acme::note_redirect_listener(redirect_port);
906
907 for listener in listeners {
908 tokio::spawn(async move {
909 loop {
910 match listener.accept().await {
911 Ok((stream, _peer)) => {
912 tokio::spawn(Server::handle_redirect_connection(stream, server_port));
913 }
914 Err(e) => eprintln!("HTTP redirect accept error: {}", e),
915 }
916 }
917 });
918 }
919
920 loop {
921 tokio::select! {
922 _ = tokio::signal::ctrl_c() => {
923 println!("\nShutting down HTTP redirect listener (SIGINT).");
924 break;
925 }
926 _ = sigterm() => {
927 println!("\nShutting down HTTP redirect listener (SIGTERM).");
928 break;
929 }
930 _ = sighup() => {
931 crate::config_reload::reload();
932 }
933 }
934 }
935 }
936
937 pub(crate) async fn handle_redirect_connection(mut stream: tokio::net::TcpStream, https_port: i32) {
940 use tokio::io::{AsyncReadExt, AsyncWriteExt};
941 let mut buf = vec![0u8; 4096];
942 let n = match stream.read(&mut buf).await {
943 Ok(n) => n,
944 Err(_) => return,
945 };
946 let text = String::from_utf8_lossy(&buf[..n]);
947
948 let uri = text.lines()
949 .next()
950 .and_then(|line| line.split_whitespace().nth(1))
951 .unwrap_or("/")
952 .to_string();
953
954 #[cfg(feature = "acme")]
957 if let Some(challenge) = crate::acme::challenge_http_response(&uri) {
958 let _ = stream.write_all(challenge.as_bytes()).await;
959 return;
960 }
961
962 let host_header = text.lines()
963 .find(|l| l.to_lowercase().starts_with("host:"))
964 .map(|l| l[5..].trim().to_string());
965
966 let location = match host_header {
967 Some(h) => {
968 let h_no_port = if h.starts_with('[') {
970 h.find(']')
972 .map(|i| h[..=i].to_string())
973 .unwrap_or(h.clone())
974 } else {
975 h.rfind(':')
976 .map(|i| h[..i].to_string())
977 .unwrap_or(h.clone())
978 };
979 if https_port == 443 {
980 format!("https://{}{}", h_no_port, uri)
981 } else {
982 format!("https://{}:{}{}", h_no_port, https_port, uri)
983 }
984 }
985 None => format!("https://localhost:{}{}", https_port, uri),
986 };
987
988 let response = format!(
989 "HTTP/1.1 301 Moved Permanently\r\nLocation: {}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n",
990 location
991 );
992 let _ = stream.write_all(response.as_bytes()).await;
993 }
994
995 async fn process_h1_tls(
996 mut stream: tokio_rustls::server::TlsStream<tokio::net::TcpStream>,
997 peer_addr: std::net::SocketAddr,
998 sni_hostname: Option<String>,
999 app: impl Application,
1000 ) -> Result<(), String> {
1001 use tokio::io::{AsyncReadExt, AsyncWriteExt};
1002
1003 let (server_ip, server_port, _) = get_ip_port_thread_count();
1004 let request_allocation_size = get_request_allocation_size();
1005
1006 let mut buffer = vec![0u8; request_allocation_size as usize];
1007 let n = match stream.read(&mut buffer).await {
1008 Ok(n) => n,
1009 Err(e) => {
1010 let raw = Server::bad_request_response(e.to_string());
1011 let _ = stream.write_all(&raw).await;
1012 return Ok(());
1013 }
1014 };
1015
1016 let mut request = match Request::parse(&buffer[..n]) {
1019 Ok(r) => r,
1020 Err(message) => {
1021 let raw = Server::bad_request_response(message);
1022 let _ = stream.write_all(&raw).await;
1023 return Ok(());
1024 }
1025 };
1026
1027 let expects_continue = match request.get_header(Header::_EXPECT.to_string()) {
1031 Some(h) if h.value.trim().eq_ignore_ascii_case("100-continue") => true,
1032 Some(h) => {
1033 let raw = Server::expectation_failed_response(format!(
1034 "417 Expectation Failed: unsupported Expect value '{}'", h.value.trim()
1035 ));
1036 let _ = stream.write_all(&raw).await;
1037 return Ok(());
1038 }
1039 None => false,
1040 };
1041
1042 if let Some(declared_len) = request
1046 .get_header(Header::_CONTENT_LENGTH.to_string())
1047 .and_then(|h| h.value.trim().parse::<u64>().ok())
1048 {
1049 let max_body_size = crate::entry_point::get_max_body_size();
1050 if max_body_size > 0 && declared_len > max_body_size {
1051 let raw = Server::payload_too_large_response(format!(
1052 "413 Payload Too Large: declared Content-Length {} exceeds the {} byte limit",
1053 declared_len, max_body_size
1054 ));
1055 let _ = stream.write_all(&raw).await;
1056 return Ok(());
1057 }
1058
1059 if expects_continue {
1062 let raw = Server::continue_response();
1063 if stream.write_all(&raw).await.is_err() {
1064 return Ok(());
1065 }
1066 }
1067
1068 while (request.body.len() as u64) < declared_len {
1069 let mut more = vec![0u8; request_allocation_size as usize];
1070 match stream.read(&mut more).await {
1071 Ok(0) | Err(_) => break, Ok(k) => request.body.extend_from_slice(&more[..k]),
1073 }
1074 }
1075 }
1076
1077 let connection = ConnectionInfo {
1078 client: Address {
1079 ip: peer_addr.ip().to_string(),
1080 port: peer_addr.port() as i32,
1081 },
1082 server: Address {
1083 ip: server_ip,
1084 port: server_port,
1085 },
1086 request_size: request_allocation_size,
1087 sni_hostname,
1088 };
1089
1090 let mut response = match app.execute(&request, &connection) {
1091 Ok(r) => r,
1092 Err(message) => {
1093 let raw = Server::bad_request_response(message);
1094 let _ = stream.write_all(&raw).await;
1095 return Ok(());
1096 }
1097 };
1098
1099 crate::metrics::record_request();
1100 crate::compression::apply_gzip(&request, &mut response);
1101 response.headers.push(Header::get_hsts_header());
1102
1103 #[cfg(feature = "http3")]
1104 response.headers.push(Header {
1105 name: Header::_ALT_SVC.to_string(),
1106 value: format!("h3=\":{}\"", server_port),
1107 });
1108 #[cfg(not(feature = "http3"))]
1109 response.headers.push(Header {
1110 name: Header::_ALT_SVC.to_string(),
1111 value: format!("h2=\":{}\"", server_port),
1112 });
1113
1114 Log::log_access(&request, &response, &peer_addr);
1115
1116 let raw = Response::generate_response(response, request);
1117 stream
1118 .write_all(&raw)
1119 .await
1120 .map_err(|e| e.to_string())?;
1121 stream.flush().await.map_err(|e| e.to_string())?;
1122
1123 Ok(())
1124 }
1125}
1126
1127#[cfg(feature = "http3")]
1128impl Server {
1129 pub async fn run_quic(
1130 app: impl Application + Send + 'static + Clone,
1131 ) {
1132 use crate::tls::create_quinn_server_config_from_vhosts;
1133 use crate::h3_handler;
1134
1135 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1136 .unwrap_or_default();
1137 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
1138 .unwrap_or_default();
1139
1140 if cert_path.is_empty() || key_path.is_empty() {
1141 return;
1142 }
1143
1144 let vhosts = crate::entry_point::get_virtual_hosts();
1145 let server_config = match create_quinn_server_config_from_vhosts(&vhosts, &cert_path, &key_path) {
1146 Ok(c) => c,
1147 Err(e) => {
1148 eprintln!("QUIC TLS setup failed: {}", e);
1149 return;
1150 }
1151 };
1152
1153 let (server_ip, server_port, _) = get_ip_port_thread_count();
1154 let bind_addr = format!("{}:{}", server_ip, server_port);
1155 let addr: std::net::SocketAddr = match bind_addr.parse() {
1156 Ok(a) => a,
1157 Err(e) => {
1158 eprintln!("Invalid QUIC bind address '{}': {}", bind_addr, e);
1159 return;
1160 }
1161 };
1162
1163 let endpoint = match quinn::Endpoint::server(server_config, addr) {
1164 Ok(e) => e,
1165 Err(e) => {
1166 eprintln!("QUIC endpoint error: {}", e);
1167 return;
1168 }
1169 };
1170
1171 println!("Listening for QUIC/HTTP3 on UDP {}:{}", server_ip, server_port);
1172
1173 loop {
1174 tokio::select! {
1175 maybe = endpoint.accept() => {
1176 match maybe {
1177 Some(incoming) => {
1178 let app = app.clone();
1179 tokio::spawn(async move {
1180 match incoming.await {
1181 Ok(conn) => {
1182 let peer_addr = conn.remote_address();
1183 if let Err(e) = h3_handler::handle_connection(conn, peer_addr, app).await {
1184 eprintln!("H3 connection error: {}", e);
1185 }
1186 }
1187 Err(e) => eprintln!("QUIC connection error: {}", e),
1188 }
1189 });
1190 }
1191 None => break,
1192 }
1193 }
1194 _ = tokio::signal::ctrl_c() => {
1195 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1196 println!("\nShutting down QUIC (SIGINT).");
1197 endpoint.close(0u32.into(), b"shutdown");
1198 break;
1199 }
1200 _ = sigterm() => {
1201 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1202 println!("\nShutting down QUIC (SIGTERM).");
1203 endpoint.close(0u32.into(), b"shutdown");
1204 break;
1205 }
1206 _ = sighup() => {
1207 crate::config_reload::reload();
1208 }
1209 }
1210 }
1211 }
1212}
1213
1214