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")]
741impl Server {
742 pub async fn run_tls(
743 listener: TcpListener,
744 pool: ThreadPool,
745 app: impl Application + Send + 'static + Clone,
746 ) {
747 use crate::tls::create_tls_acceptor_from_vhosts;
748 use crate::h2_handler;
749
750 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
751 .unwrap_or_default();
752 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
753 .unwrap_or_default();
754
755 if cert_path.is_empty() || key_path.is_empty() {
756 println!("No TLS certificate configured — serving plain HTTP/1.1.");
757 tokio::task::block_in_place(|| Server::run(listener, pool, app));
758 return;
759 }
760
761 let vhosts = crate::entry_point::get_virtual_hosts();
762 let mut tls_acceptor = match create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
763 Ok(a) => a,
764 Err(e) => {
765 eprintln!("TLS setup failed: {}", e);
766 return;
767 }
768 };
769
770 listener
771 .set_nonblocking(true)
772 .expect("failed to set TCP listener to non-blocking");
773 let tokio_listener = tokio::net::TcpListener::from_std(listener)
774 .expect("failed to convert TCP listener to tokio");
775
776 println!("Listening for TLS connections (HTTP/1.1 + HTTP/2)...");
777
778 loop {
779 tokio::select! {
780 result = tokio_listener.accept() => {
781 match result {
782 Ok((tcp_stream, peer_addr)) => {
783 let acceptor = tls_acceptor.clone();
784 let app = app.clone();
785 tokio::spawn(async move {
786 match acceptor.accept(tcp_stream).await {
787 Ok(tls_stream) => {
788 let server_conn = tls_stream.get_ref().1;
789 let sni = server_conn.server_name().map(|s| s.to_string());
790 let protocol = server_conn
791 .alpn_protocol()
792 .map(|p| p.to_vec());
793
794 match protocol.as_deref() {
795 Some(b"h2") => {
796 if let Err(e) =
797 h2_handler::handle_connection(tls_stream, peer_addr, sni, app)
798 .await
799 {
800 eprintln!("H2 connection error: {}", e);
801 }
802 }
803 _ => {
804 if let Err(e) =
805 Server::process_h1_tls(tls_stream, peer_addr, sni, app).await
806 {
807 eprintln!("H1 TLS error: {}", e);
808 }
809 }
810 }
811 }
812 Err(e) => eprintln!("TLS handshake failed: {}", e),
813 }
814 });
815 }
816 Err(e) => eprintln!("TCP accept error: {}", e),
817 }
818 }
819 _ = tokio::signal::ctrl_c() => {
820 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
821 println!("\nShutting down gracefully (SIGINT).");
822 break;
823 }
824 _ = sigterm() => {
825 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
826 println!("\nShutting down gracefully (SIGTERM).");
827 break;
828 }
829 _ = sighup() => {
830 crate::config_reload::reload();
831 let vhosts = crate::entry_point::get_virtual_hosts();
832 if let Ok(new_acceptor) = create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
833 tls_acceptor = new_acceptor;
834 println!("[TLS] Certificates reloaded ({} virtual hosts).", vhosts.len());
835 }
836 }
837 }
838 }
839 }
840
841 pub async fn run_redirect() {
845 use std::env;
846 use tokio::io::{AsyncReadExt, AsyncWriteExt};
847 use tokio::net::TcpListener as TokioListener;
848
849 let cert_path = env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
850 .unwrap_or_default();
851 if cert_path.is_empty() {
852 return;
853 }
854
855 let redirect_port_str = env::var(crate::entry_point::Config::RWS_CONFIG_HTTP_REDIRECT_PORT)
856 .unwrap_or_default();
857 if redirect_port_str.is_empty() {
858 return;
859 }
860
861 let redirect_port: u16 = match redirect_port_str.parse() {
862 Ok(p) => p,
863 Err(_) => {
864 eprintln!("Invalid RWS_CONFIG_HTTP_REDIRECT_PORT: {}", redirect_port_str);
865 return;
866 }
867 };
868
869 let (server_ip, server_port, _) = get_ip_port_thread_count();
870 let bind_addr = format!("{}:{}", server_ip, redirect_port);
871
872 let listener = match TokioListener::bind(&bind_addr).await {
873 Ok(l) => l,
874 Err(e) => {
875 eprintln!("HTTP redirect listener error on {}: {}", bind_addr, e);
876 return;
877 }
878 };
879
880 println!("HTTP→HTTPS redirect listening on http://{}:{}", server_ip, redirect_port);
881
882 loop {
883 tokio::select! {
884 result = listener.accept() => {
885 match result {
886 Ok((mut stream, _peer)) => {
887 let https_port = server_port;
888 tokio::spawn(async move {
889 let mut buf = vec![0u8; 4096];
890 let n = match stream.read(&mut buf).await {
891 Ok(n) => n,
892 Err(_) => return,
893 };
894 let text = String::from_utf8_lossy(&buf[..n]);
895
896 let uri = text.lines()
897 .next()
898 .and_then(|line| line.split_whitespace().nth(1))
899 .unwrap_or("/")
900 .to_string();
901
902 let host_header = text.lines()
903 .find(|l| l.to_lowercase().starts_with("host:"))
904 .map(|l| l[5..].trim().to_string());
905
906 let location = match host_header {
907 Some(h) => {
908 let h_no_port = if h.starts_with('[') {
910 h.find(']')
912 .map(|i| h[..=i].to_string())
913 .unwrap_or(h.clone())
914 } else {
915 h.rfind(':')
916 .map(|i| h[..i].to_string())
917 .unwrap_or(h.clone())
918 };
919 if https_port == 443 {
920 format!("https://{}{}", h_no_port, uri)
921 } else {
922 format!("https://{}:{}{}", h_no_port, https_port, uri)
923 }
924 }
925 None => format!("https://localhost:{}{}", https_port, uri),
926 };
927
928 let response = format!(
929 "HTTP/1.1 301 Moved Permanently\r\nLocation: {}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n",
930 location
931 );
932 let _ = stream.write_all(response.as_bytes()).await;
933 });
934 }
935 Err(e) => eprintln!("HTTP redirect accept error: {}", e),
936 }
937 }
938 _ = tokio::signal::ctrl_c() => {
939 println!("\nShutting down HTTP redirect listener (SIGINT).");
940 break;
941 }
942 _ = sigterm() => {
943 println!("\nShutting down HTTP redirect listener (SIGTERM).");
944 break;
945 }
946 _ = sighup() => {
947 crate::config_reload::reload();
948 }
949 }
950 }
951 }
952
953 async fn process_h1_tls(
954 mut stream: tokio_rustls::server::TlsStream<tokio::net::TcpStream>,
955 peer_addr: std::net::SocketAddr,
956 sni_hostname: Option<String>,
957 app: impl Application,
958 ) -> Result<(), String> {
959 use tokio::io::{AsyncReadExt, AsyncWriteExt};
960
961 let (server_ip, server_port, _) = get_ip_port_thread_count();
962 let request_allocation_size = get_request_allocation_size();
963
964 let mut buffer = vec![0u8; request_allocation_size as usize];
965 let n = match stream.read(&mut buffer).await {
966 Ok(n) => n,
967 Err(e) => {
968 let raw = Server::bad_request_response(e.to_string());
969 let _ = stream.write_all(&raw).await;
970 return Ok(());
971 }
972 };
973
974 let mut request = match Request::parse(&buffer[..n]) {
977 Ok(r) => r,
978 Err(message) => {
979 let raw = Server::bad_request_response(message);
980 let _ = stream.write_all(&raw).await;
981 return Ok(());
982 }
983 };
984
985 let expects_continue = match request.get_header(Header::_EXPECT.to_string()) {
989 Some(h) if h.value.trim().eq_ignore_ascii_case("100-continue") => true,
990 Some(h) => {
991 let raw = Server::expectation_failed_response(format!(
992 "417 Expectation Failed: unsupported Expect value '{}'", h.value.trim()
993 ));
994 let _ = stream.write_all(&raw).await;
995 return Ok(());
996 }
997 None => false,
998 };
999
1000 if let Some(declared_len) = request
1004 .get_header(Header::_CONTENT_LENGTH.to_string())
1005 .and_then(|h| h.value.trim().parse::<u64>().ok())
1006 {
1007 let max_body_size = crate::entry_point::get_max_body_size();
1008 if max_body_size > 0 && declared_len > max_body_size {
1009 let raw = Server::payload_too_large_response(format!(
1010 "413 Payload Too Large: declared Content-Length {} exceeds the {} byte limit",
1011 declared_len, max_body_size
1012 ));
1013 let _ = stream.write_all(&raw).await;
1014 return Ok(());
1015 }
1016
1017 if expects_continue {
1020 let raw = Server::continue_response();
1021 if stream.write_all(&raw).await.is_err() {
1022 return Ok(());
1023 }
1024 }
1025
1026 while (request.body.len() as u64) < declared_len {
1027 let mut more = vec![0u8; request_allocation_size as usize];
1028 match stream.read(&mut more).await {
1029 Ok(0) | Err(_) => break, Ok(k) => request.body.extend_from_slice(&more[..k]),
1031 }
1032 }
1033 }
1034
1035 let connection = ConnectionInfo {
1036 client: Address {
1037 ip: peer_addr.ip().to_string(),
1038 port: peer_addr.port() as i32,
1039 },
1040 server: Address {
1041 ip: server_ip,
1042 port: server_port,
1043 },
1044 request_size: request_allocation_size,
1045 sni_hostname,
1046 };
1047
1048 let mut response = match app.execute(&request, &connection) {
1049 Ok(r) => r,
1050 Err(message) => {
1051 let raw = Server::bad_request_response(message);
1052 let _ = stream.write_all(&raw).await;
1053 return Ok(());
1054 }
1055 };
1056
1057 crate::metrics::record_request();
1058 crate::compression::apply_gzip(&request, &mut response);
1059 response.headers.push(Header::get_hsts_header());
1060
1061 #[cfg(feature = "http3")]
1062 response.headers.push(Header {
1063 name: Header::_ALT_SVC.to_string(),
1064 value: format!("h3=\":{}\"", server_port),
1065 });
1066 #[cfg(not(feature = "http3"))]
1067 response.headers.push(Header {
1068 name: Header::_ALT_SVC.to_string(),
1069 value: format!("h2=\":{}\"", server_port),
1070 });
1071
1072 Log::log_access(&request, &response, &peer_addr);
1073
1074 let raw = Response::generate_response(response, request);
1075 stream
1076 .write_all(&raw)
1077 .await
1078 .map_err(|e| e.to_string())?;
1079 stream.flush().await.map_err(|e| e.to_string())?;
1080
1081 Ok(())
1082 }
1083}
1084
1085#[cfg(feature = "http3")]
1086impl Server {
1087 pub async fn run_quic(
1088 app: impl Application + Send + 'static + Clone,
1089 ) {
1090 use crate::tls::create_quinn_server_config_from_vhosts;
1091 use crate::h3_handler;
1092
1093 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1094 .unwrap_or_default();
1095 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
1096 .unwrap_or_default();
1097
1098 if cert_path.is_empty() || key_path.is_empty() {
1099 return;
1100 }
1101
1102 let vhosts = crate::entry_point::get_virtual_hosts();
1103 let server_config = match create_quinn_server_config_from_vhosts(&vhosts, &cert_path, &key_path) {
1104 Ok(c) => c,
1105 Err(e) => {
1106 eprintln!("QUIC TLS setup failed: {}", e);
1107 return;
1108 }
1109 };
1110
1111 let (server_ip, server_port, _) = get_ip_port_thread_count();
1112 let bind_addr = format!("{}:{}", server_ip, server_port);
1113 let addr: std::net::SocketAddr = match bind_addr.parse() {
1114 Ok(a) => a,
1115 Err(e) => {
1116 eprintln!("Invalid QUIC bind address '{}': {}", bind_addr, e);
1117 return;
1118 }
1119 };
1120
1121 let endpoint = match quinn::Endpoint::server(server_config, addr) {
1122 Ok(e) => e,
1123 Err(e) => {
1124 eprintln!("QUIC endpoint error: {}", e);
1125 return;
1126 }
1127 };
1128
1129 println!("Listening for QUIC/HTTP3 on UDP {}:{}", server_ip, server_port);
1130
1131 loop {
1132 tokio::select! {
1133 maybe = endpoint.accept() => {
1134 match maybe {
1135 Some(incoming) => {
1136 let app = app.clone();
1137 tokio::spawn(async move {
1138 match incoming.await {
1139 Ok(conn) => {
1140 let peer_addr = conn.remote_address();
1141 if let Err(e) = h3_handler::handle_connection(conn, peer_addr, app).await {
1142 eprintln!("H3 connection error: {}", e);
1143 }
1144 }
1145 Err(e) => eprintln!("QUIC connection error: {}", e),
1146 }
1147 });
1148 }
1149 None => break,
1150 }
1151 }
1152 _ = tokio::signal::ctrl_c() => {
1153 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1154 println!("\nShutting down QUIC (SIGINT).");
1155 endpoint.close(0u32.into(), b"shutdown");
1156 break;
1157 }
1158 _ = sigterm() => {
1159 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1160 println!("\nShutting down QUIC (SIGTERM).");
1161 endpoint.close(0u32.into(), b"shutdown");
1162 break;
1163 }
1164 _ = sighup() => {
1165 crate::config_reload::reload();
1166 }
1167 }
1168 }
1169 }
1170}
1171
1172