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