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