1#[cfg(all(test, not(target_arch = "wasm32")))]
12pub mod tests;
13#[cfg(all(test, not(target_arch = "wasm32")))]
14mod example;
15#[cfg(feature = "http2")]
16pub(crate) mod http1_async;
17#[cfg(feature = "http2")]
18pub(crate) mod body_stream;
19#[cfg(feature = "http2")]
20pub(crate) mod body_pump;
21#[cfg(feature = "http2")]
22pub(crate) mod sendfile;
23#[cfg(feature = "http2")]
24pub mod per_core;
25pub(crate) mod framing;
26
27#[cfg(not(target_arch = "wasm32"))]
33use std::io::prelude::*;
34#[cfg(not(target_arch = "wasm32"))]
35use std::borrow::Borrow;
36#[cfg(not(target_arch = "wasm32"))]
37use std::net::{IpAddr, SocketAddr, TcpListener};
38#[cfg(not(target_arch = "wasm32"))]
39use std::str::FromStr;
40#[cfg(not(target_arch = "wasm32"))]
41use std::time::Duration;
42
43#[cfg(not(target_arch = "wasm32"))]
44use crate::request::{METHOD, Request};
45#[cfg(not(target_arch = "wasm32"))]
46use crate::response::{Response, STATUS_CODE_REASON_PHRASE};
47#[cfg(not(target_arch = "wasm32"))]
48use crate::app::App;
49#[cfg(not(target_arch = "wasm32"))]
50use crate::application::Application;
51#[cfg(not(target_arch = "wasm32"))]
52use crate::entry_point::{bootstrap, get_ip_port_thread_count, get_request_allocation_size, set_default_values};
53#[cfg(not(target_arch = "wasm32"))]
54use crate::header::Header;
55#[cfg(not(target_arch = "wasm32"))]
56use crate::log::Log;
57#[cfg(not(target_arch = "wasm32"))]
58use crate::mime_type::MimeType;
59#[cfg(not(target_arch = "wasm32"))]
60use crate::range::{ContentRange, Range};
61#[cfg(not(target_arch = "wasm32"))]
62use crate::symbol::SYMBOL;
63#[cfg(not(target_arch = "wasm32"))]
64use crate::thread_pool::ThreadPool;
65
66#[cfg(not(target_arch = "wasm32"))]
67pub const REQUEST_HEAD_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30);
72
73pub struct Server {}
74#[cfg(not(target_arch = "wasm32"))]
75impl Server {
76 pub fn process_request(mut stream: impl Read + Write + Unpin, peer_addr: SocketAddr) -> Vec<u8> {
77 let request_allocation_size = get_request_allocation_size();
78 let mut buffer = vec![0; request_allocation_size as usize];
79 let boxed_read = stream.read(&mut buffer);
80 if boxed_read.is_err() {
81 let message = boxed_read.err().unwrap().to_string();
82 eprintln!("unable to read TCP stream {}", &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 boxed_read.unwrap();
93 let request : &[u8] = &buffer;
94
95 let boxed_request = Request::parse_request(request);
100 if boxed_request.is_err() {
101 let message = boxed_request.err().unwrap();
102 eprintln!("unable to parse request: {}", &message);
103
104 let raw_response = Server::bad_request_response(message);
105 let boxed_stream = stream.write(raw_response.borrow());
106 if boxed_stream.is_ok() {
107 stream.flush().unwrap();
108 };
109 return raw_response;
110 }
111
112
113 let request: Request = boxed_request.unwrap();
114 let (response, request) = App::handle_request(request);
115
116
117 let log_request_response = Log::combined(&request, &response, &peer_addr);
118 println!("{}", log_request_response);
119 let raw_response = Response::generate_response(response, request);
120
121 let boxed_stream = stream.write(raw_response.borrow());
122 if boxed_stream.is_ok() {
123 stream.flush().unwrap();
124 };
125
126 raw_response
127 }
128
129 pub fn bad_request_response(message: String) -> Vec<u8> {
130 let error_request = Request {
131 method: METHOD.get.to_string(),
132 request_uri: "".to_string(),
133 http_version: "".to_string(),
134 headers: vec![],
135 body: Default::default(),
136 };
137
138 let size = message.chars().count() as u64;
139 let content_range = ContentRange {
140 unit: Range::BYTES.to_string(),
141 range: Range { start: 0, end: size },
142 size: size.to_string(),
143 body: Vec::from(message.as_bytes()),
144 content_type: MimeType::TEXT_PLAIN.to_string(),
145 };
146
147 let header_list = Header::get_header_list(&error_request);
148 let error_response: Response = Response::get_response(
149 STATUS_CODE_REASON_PHRASE.n400_bad_request,
150 Some(header_list),
151 Some(vec![content_range])
152 );
153
154 let response = Response::generate_response(error_response, error_request);
155 return response;
156 }
157
158 pub fn payload_too_large_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: Default::default(),
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.into(), value: "close".into() });
183 let error_response: Response = Response::get_response(
184 STATUS_CODE_REASON_PHRASE.n413_payload_too_large,
185 Some(header_list),
186 Some(vec![content_range])
187 );
188
189 Response::generate_response(error_response, error_request)
190 }
191
192 pub fn header_fields_too_large_response() -> Vec<u8> {
196 Server::closing_error_response(
197 STATUS_CODE_REASON_PHRASE.n431_request_header_fields_too_large,
198 format!("431 Request Header Fields Too Large: the request head exceeds {} bytes", framing::MAX_HEAD_SIZE),
199 )
200 }
201
202 pub fn request_timeout_response() -> Vec<u8> {
206 Server::closing_error_response(
207 STATUS_CODE_REASON_PHRASE.n408_request_timeout,
208 format!("408 Request Timeout: the request head took longer than {} s", REQUEST_HEAD_TIMEOUT.as_secs()),
209 )
210 }
211
212 fn closing_error_response(status: &'static crate::response::StatusCodeReasonPhrase, message: String) -> Vec<u8> {
214 let error_request = Request {
215 method: METHOD.get.to_string(),
216 request_uri: "".to_string(),
217 http_version: "".to_string(),
218 headers: vec![],
219 body: Default::default(),
220 };
221
222 let size = message.chars().count() as u64;
223 let content_range = ContentRange {
224 unit: Range::BYTES.to_string(),
225 range: Range { start: 0, end: size },
226 size: size.to_string(),
227 body: Vec::from(message.as_bytes()),
228 content_type: MimeType::TEXT_PLAIN.to_string(),
229 };
230
231 let mut header_list = Header::get_header_list(&error_request);
232 header_list.push(Header { name: Header::_CONNECTION.into(), value: "close".into() });
233 let error_response: Response = Response::get_response(status, Some(header_list), Some(vec![content_range]));
234
235 Response::generate_response(error_response, error_request)
236 }
237
238 pub fn continue_response() -> Vec<u8> {
244 let dummy_request = Request {
245 method: METHOD.get.to_string(),
246 request_uri: "".to_string(),
247 http_version: "".to_string(),
248 headers: vec![],
249 body: Default::default(),
250 };
251 let response = Response::get_response(STATUS_CODE_REASON_PHRASE.n100_continue, None, None);
252 Response::generate_response(response, dummy_request)
253 }
254
255 pub fn expectation_failed_response(message: String) -> Vec<u8> {
260 let error_request = Request {
261 method: METHOD.get.to_string(),
262 request_uri: "".to_string(),
263 http_version: "".to_string(),
264 headers: vec![],
265 body: Default::default(),
266 };
267
268 let size = message.chars().count() as u64;
269 let content_range = ContentRange {
270 unit: Range::BYTES.to_string(),
271 range: Range { start: 0, end: size },
272 size: size.to_string(),
273 body: Vec::from(message.as_bytes()),
274 content_type: MimeType::TEXT_PLAIN.to_string(),
275 };
276
277 let mut header_list = Header::get_header_list(&error_request);
278 header_list.push(Header { name: Header::_CONNECTION.into(), value: "close".into() });
279 let error_response: Response = Response::get_response(
280 STATUS_CODE_REASON_PHRASE.n417_expectation_failed,
281 Some(header_list),
282 Some(vec![content_range])
283 );
284
285 Response::generate_response(error_response, error_request)
286 }
287
288 pub fn process(mut stream: impl Read + Write + Unpin,
289 connection: ConnectionInfo,
290 app: impl Application) -> Result<(), String> {
291
292 let request_allocation_size = connection.request_size;
293 let client = connection.client.clone();
294 let client_addr = SocketAddr::new(IpAddr::from_str(client.ip.as_str()).unwrap(), client.port as u16);
295
296 let max_body_size = crate::entry_point::get_max_body_size();
297
298 let mut pending: Vec<u8> = Vec::new();
301 let mut read_buffer = vec![0u8; request_allocation_size as usize];
302
303 'session: loop {
304 let mut head_started: Option<std::time::Instant> = None;
309 let head_len = loop {
310 framing::skip_leading_empty_lines(&mut pending);
311 match framing::scan_head(&pending) {
312 framing::HeadScan::Complete(n) => break Some(n),
313 framing::HeadScan::TooLarge => {
314 let _ = stream.write_all(&Server::header_fields_too_large_response());
315 let _ = stream.flush();
316 return Err("request head too large".to_string());
317 }
318 framing::HeadScan::Incomplete => {}
319 }
320 if !pending.is_empty() && head_started.is_none() {
321 head_started = Some(std::time::Instant::now());
322 }
323 match stream.read(&mut read_buffer) {
324 Ok(0) | Err(_) => break None,
326 Ok(n) => pending.extend_from_slice(&read_buffer[..n]),
327 }
328 let started = *head_started.get_or_insert_with(std::time::Instant::now);
329 if started.elapsed() > REQUEST_HEAD_TIMEOUT && framing::scan_head(&pending) == framing::HeadScan::Incomplete {
330 let _ = stream.write_all(&Server::request_timeout_response());
331 let _ = stream.flush();
332 return Err("request head timed out".to_string());
333 }
334 };
335 let Some(head_len) = head_len else { break };
336
337 let parsed = Request::parse(&pending[..head_len])
338 .and_then(|request| framing::validate_head(&pending[..head_len], &request).map(|_| request))
339 .and_then(|request| framing::body_framing(&request).map(|f| (request, f)));
340 pending.drain(..head_len);
341 let (mut request, body_framing) = match parsed {
342 Ok(parsed) => parsed,
343 Err(message) => {
344 let _ = stream.write_all(&Server::bad_request_response(message.clone()));
345 let _ = stream.flush();
346 return Err(message);
347 }
348 };
349
350 let expects_continue = match request.header(Header::_EXPECT) {
354 Some(h) if h.value.trim().eq_ignore_ascii_case("100-continue") => true,
355 Some(h) => {
356 let raw_response = Server::expectation_failed_response(format!(
357 "417 Expectation Failed: unsupported Expect value '{}'", h.value.trim()
358 ));
359 let _ = stream.write_all(&raw_response);
360 let _ = stream.flush();
361 break;
362 }
363 None => false,
364 };
365
366 match body_framing {
367 framing::BodyFraming::None => {}
368 framing::BodyFraming::Length(declared_len) => {
369 if max_body_size > 0 && declared_len > max_body_size {
370 let raw_response = Server::payload_too_large_response(format!(
371 "413 Payload Too Large: declared Content-Length {} exceeds the {} byte limit",
372 declared_len, max_body_size
373 ));
374 let _ = stream.write_all(&raw_response);
375 let _ = stream.flush();
376 break;
377 }
378
379 if expects_continue && (pending.len() as u64) < declared_len {
382 if stream.write_all(&Server::continue_response()).and_then(|_| stream.flush()).is_err() {
383 break;
384 }
385 }
386
387 while (pending.len() as u64) < declared_len {
388 match stream.read(&mut read_buffer) {
389 Ok(0) | Err(_) => break 'session, Ok(k) => pending.extend_from_slice(&read_buffer[..k]),
391 }
392 }
393 request.body = pending.drain(..declared_len as usize).collect::<Vec<u8>>().into();
394 }
395 framing::BodyFraming::Chunked => {
396 if expects_continue && pending.is_empty() {
397 if stream.write_all(&Server::continue_response()).and_then(|_| stream.flush()).is_err() {
398 break;
399 }
400 }
401
402 let mut decoder = framing::ChunkedBody::new(max_body_size);
403 loop {
404 match decoder.feed(&pending) {
405 Ok((consumed, done)) => {
406 pending.drain(..consumed);
407 if done { break; }
408 }
409 Err(framing::ChunkError::TooLarge) => {
410 let raw_response = Server::payload_too_large_response(format!(
411 "413 Payload Too Large: chunked body exceeds the {} byte limit", max_body_size
412 ));
413 let _ = stream.write_all(&raw_response);
414 let _ = stream.flush();
415 break 'session;
416 }
417 Err(framing::ChunkError::Malformed(message)) => {
418 let _ = stream.write_all(&Server::bad_request_response(message.clone()));
419 let _ = stream.flush();
420 return Err(message);
421 }
422 }
423 match stream.read(&mut read_buffer) {
424 Ok(0) | Err(_) => break 'session,
425 Ok(k) => pending.extend_from_slice(&read_buffer[..k]),
426 }
427 }
428 request.body = decoder.body.into();
429 }
430 }
431
432 let keep_alive = framing::keep_alive(&request);
433
434 let mut response = match app.execute(&request, &connection) {
435 Ok(r) => r,
436 Err(message) => {
437 let raw_response = Server::bad_request_response(message.clone());
438 let boxed_stream = stream.write(raw_response.borrow());
439 if boxed_stream.is_ok() { stream.flush().unwrap(); }
440 return Err(message);
441 }
442 };
443
444 crate::metrics::record_request();
445 crate::compression::apply_gzip(&request, &mut response);
446 response.drop_content_for_status();
447
448 response.headers.push(Header {
449 name: Header::_CONNECTION.into(),
450 value: if keep_alive { "keep-alive".into() } else { "close".into() },
451 });
452
453 Log::log_access(&request, &response, &client_addr);
454
455 if let Some(reader) = response.stream_pipe.take() {
456 if let Err(e) = Server::pipe_stream(&mut stream, response, request, reader) {
457 return Err(e);
458 }
459 } else if let Some(ref filepath) = response.stream_file.clone() {
460 if let Err(e) = Server::write_chunked_file(&mut stream, response, request, filepath) {
461 return Err(e);
462 }
463 } else {
464 let raw_response = Response::generate_response(response, request);
465 if let Err(e) = stream.write_all(raw_response.borrow()) {
467 return Err(e.to_string());
468 }
469 stream.flush().unwrap();
470 }
471
472 if !keep_alive { break; }
473 }
474
475 Ok(())
476 }
477
478 pub(crate) fn write_chunked_file(
481 stream: &mut impl Write,
482 response: Response,
483 request: Request,
484 filepath: &str,
485 ) -> Result<(), String> {
486 use std::fs::File;
487 use std::io::Read as _;
488
489 let (head, chunked) = Server::stream_file_head(response);
490 stream.write_all(&head).map_err(|e| e.to_string())?;
491
492 if request.method != METHOD.head {
493 let mut file = File::open(filepath).map_err(|e| e.to_string())?;
494 let mut buf = vec![0u8; 65536];
495 loop {
496 let n = file.read(&mut buf).map_err(|e| e.to_string())?;
497 if n == 0 { break; }
498 if chunked {
499 stream.write_all(format!("{:x}\r\n", n).as_bytes()).map_err(|e| e.to_string())?;
501 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
502 stream.write_all(b"\r\n").map_err(|e| e.to_string())?;
503 } else {
504 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
505 }
506 }
507 if chunked {
508 stream.write_all(b"0\r\n\r\n").map_err(|e| e.to_string())?;
510 }
511 }
512
513 stream.flush().map_err(|e| e.to_string())
514 }
515
516 pub(crate) fn stream_file_head(mut response: Response) -> (Vec<u8>, bool) {
523 let chunked = !response.headers.iter().any(|h| h.name.eq_ignore_ascii_case(Header::_CONTENT_LENGTH));
524 if chunked {
525 response.headers.push(Header {
526 name: Header::_TRANSFER_ENCODING.into(),
527 value: "chunked".into(),
528 });
529 }
530
531 let status = [
533 response.http_version.clone(),
534 response.status_code.to_string(),
535 Header::single_line(&response.reason_phrase).into_owned(),
536 ].join(SYMBOL.whitespace);
537
538 let mut headers_str = SYMBOL.new_line_carriage_return.to_string();
539 for header in &response.headers {
540 headers_str.push_str(&Header::single_line(&header.name));
541 headers_str.push_str(Header::NAME_VALUE_SEPARATOR);
542 headers_str.push_str(&Header::single_line(&header.value));
543 headers_str.push_str(SYMBOL.new_line_carriage_return);
544 }
545 let head = format!("{}{}{}", status, headers_str, SYMBOL.new_line_carriage_return);
546 (head.into_bytes(), chunked)
547 }
548
549 pub(crate) fn pipe_stream(
557 stream: &mut impl Write,
558 mut response: Response,
559 request: Request,
560 mut reader: Box<dyn std::io::Read + Send>,
561 ) -> Result<(), String> {
562 let backend_is_chunked = response.headers.iter().any(|h| {
566 h.name.eq_ignore_ascii_case("transfer-encoding")
567 && h.value.to_lowercase().contains("chunked")
568 });
569
570 response.headers.retain(|h| !h.name.eq_ignore_ascii_case("content-length"));
571 if !backend_is_chunked {
572 response.headers.push(Header {
573 name: Header::_TRANSFER_ENCODING.into(),
574 value: "chunked".into(),
575 });
576 }
577
578 let status = [
579 response.http_version.clone(),
580 response.status_code.to_string(),
581 Header::single_line(&response.reason_phrase).into_owned(),
582 ].join(SYMBOL.whitespace);
583
584 let mut head = format!("{}\r\n", status);
585 for header in &response.headers {
586 head.push_str(&Header::single_line(&header.name));
587 head.push_str(Header::NAME_VALUE_SEPARATOR);
588 head.push_str(&Header::single_line(&header.value));
589 head.push_str(SYMBOL.new_line_carriage_return);
590 }
591 head.push_str(SYMBOL.new_line_carriage_return);
592 stream.write_all(head.as_bytes()).map_err(|e| e.to_string())?;
593
594 if request.method != METHOD.head {
595 let mut buf = [0u8; 8192];
596 if backend_is_chunked {
597 loop {
600 match reader.read(&mut buf) {
601 Ok(0) | Err(_) => break,
602 Ok(n) => {
603 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
604 stream.flush().map_err(|e| e.to_string())?;
605 }
606 }
607 }
608 } else {
609 loop {
613 match reader.read(&mut buf) {
614 Ok(0) | Err(_) => break,
615 Ok(n) => {
616 stream
617 .write_all(format!("{:x}\r\n", n).as_bytes())
618 .map_err(|e| e.to_string())?;
619 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
620 stream.write_all(b"\r\n").map_err(|e| e.to_string())?;
621 stream.flush().map_err(|e| e.to_string())?;
622 }
623 }
624 }
625 stream.write_all(b"0\r\n\r\n").map_err(|e| e.to_string())?;
626 }
627 }
628
629 stream.flush().map_err(|e| e.to_string())
630 }
631
632 pub fn setup() -> Result<(TcpListener, ThreadPool), String> {
635 let info = Log::info("Rust Web Server");
636 println!("{}", info);
637
638 let usage_info = Log::usage_information();
639 println!("{}", usage_info);
640
641
642 println!("RWS Configuration Start: \n");
643
644 set_default_values();
645 bootstrap();
646
647 #[cfg(feature = "secrets")]
648 crate::secrets::resolve_env_vars().map_err(|e| e.to_string())?;
649
650 println!("\nRWS Configuration End\n\n");
651
652
653 let (ip, port, thread_count) = get_ip_port_thread_count();
654
655
656 let mut ip_readable = ip.to_string();
657
658 if ip.contains(":") {
659 ip_readable = [SYMBOL.opening_square_bracket, &ip, SYMBOL.closing_square_bracket].join("");
660 }
661
662 let bind_addr = [ip_readable, SYMBOL.colon.to_string(), port.to_string()].join(SYMBOL.empty_string);
663
664 #[cfg(feature = "http2")]
665 let protocol = {
666 let cert = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE).unwrap_or_default();
667 if cert.is_empty() { "http" } else { "https" }
668 };
669 #[cfg(not(feature = "http2"))]
670 let protocol = "http";
671
672 println!("Setting up {}://{}...", protocol, &bind_addr);
673
674 let boxed_listener = TcpListener::bind(&bind_addr);
675 if boxed_listener.is_err() {
676 let message = format!("unable to set up TCP listener: {}", boxed_listener.err().unwrap());
677 return Err(message);
678 }
679
680 let listener = boxed_listener.unwrap();
681 let pool = ThreadPool::new(thread_count as usize);
682
683
684 let server_url_thread_count = Log::server_url_thread_count(protocol, &bind_addr, thread_count);
685 println!("{}", server_url_thread_count);
686
687 Ok((listener, pool))
688 }
689
690 pub fn run(listener: TcpListener,
698 pool: ThreadPool,
699 app: impl Application + Send + 'static + Clone) {
700 #[cfg(feature = "http1")]
701 {
702 use std::sync::Arc;
703 use std::sync::atomic::{AtomicBool, Ordering};
704
705 let shutdown = Arc::new(AtomicBool::new(false));
706 let s = shutdown.clone();
707 if let Err(e) = ctrlc::set_handler(move || {
708 s.store(true, Ordering::SeqCst);
709 }) {
710 eprintln!("unable to install signal handler: {}", e);
711 }
712 crate::config_reload::install_sighup_handler();
713 if let Err(e) = listener.set_nonblocking(true) {
714 eprintln!("unable to set non-blocking listener: {}", e);
715 }
716
717 loop {
718 if shutdown.load(Ordering::SeqCst) {
719 break;
720 }
721 if crate::config_reload::RELOAD_REQUESTED
722 .compare_exchange(true, false, Ordering::SeqCst, Ordering::Relaxed)
723 .is_ok()
724 {
725 crate::config_reload::reload();
726 }
727 match listener.accept() {
728 Ok((stream, peer_addr)) => {
729 Server::dispatch_connection(stream, peer_addr, &pool, app.clone());
730 }
731 Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
732 std::thread::sleep(Duration::from_millis(10));
733 }
734 Err(e) => {
735 eprintln!("accept error: {}", e);
736 break;
737 }
738 }
739 }
740
741 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
742 println!("Shutting down — waiting for in-flight connections to finish");
743 pool.join();
744 println!("Server stopped");
745 }
746
747 #[cfg(not(feature = "http1"))]
748 {
749 for boxed_stream in listener.incoming() {
750 match boxed_stream {
751 Err(e) => {
752 eprintln!("unable to get TCP stream: {}", e);
753 return;
754 }
755 Ok(stream) => {
756 let peer_addr = match stream.peer_addr() {
757 Ok(a) => a,
758 Err(e) => {
759 eprintln!("unable to read peer addr: {}", e);
760 return;
761 }
762 };
763 Server::dispatch_connection(stream, peer_addr, &pool, app.clone());
764 }
765 }
766 }
767 }
768 }
769
770 fn dispatch_connection(
771 stream: std::net::TcpStream,
772 peer_addr: std::net::SocketAddr,
773 pool: &ThreadPool,
774 app: impl Application + Send + 'static + Clone,
775 ) {
776 print!("Connection established, ");
777 if let Ok(local) = stream.local_addr() {
778 print!("local addr: {}", local);
779 }
780 println!(", peer addr: {}", peer_addr);
781
782 let (server_ip, server_port, _thread_count) = get_ip_port_thread_count();
783 let connection = ConnectionInfo {
784 client: Address {
785 ip: peer_addr.ip().to_string(),
786 port: peer_addr.port() as i32,
787 },
788 server: Address {
789 ip: server_ip,
790 port: server_port,
791 },
792 request_size: get_request_allocation_size(),
793 sni_hostname: None,
794 };
795
796 if let Err(e) = stream.set_read_timeout(Some(Duration::from_secs(30))) {
797 eprintln!("failed to set read timeout: {}", e);
798 }
799
800 pool.execute(move || {
801 crate::metrics::connection_open();
802 let result = Server::process(stream, connection, app);
803 crate::metrics::connection_close();
804 if let Err(msg) = result {
805 crate::metrics::record_error();
806 eprintln!("{}", msg);
807 }
808 });
809 }
810
811}
812
813#[derive(Clone)]
815pub struct ConnectionInfo {
816 pub client: Address,
818 pub server: Address,
820 pub request_size: i64,
822 pub sni_hostname: Option<String>,
825}
826
827#[derive(Clone)]
829pub struct Address {
830 pub ip: String,
831 pub port: i32
832}
833
834impl ConnectionInfo {
835 pub fn peer_addr(&self) -> Option<std::net::SocketAddr> {
838 self.client.to_socket_addr()
839 }
840}
841
842impl Address {
843 pub fn to_socket_addr(&self) -> Option<std::net::SocketAddr> {
846 let ip: std::net::IpAddr = self.ip.parse().ok()?;
847 let port = u16::try_from(self.port).ok()?;
848 Some(std::net::SocketAddr::new(ip, port))
849 }
850}
851
852#[cfg(feature = "http2")]
855async fn serve_tls_connection(
856 tcp_stream: tokio::net::TcpStream,
857 peer_addr: std::net::SocketAddr,
858 acceptor: tokio_rustls::TlsAcceptor,
859 app: impl Application + Send + 'static + Clone,
860) {
861 let _ = tcp_stream.set_nodelay(true);
862 let handshake = tokio::time::timeout(http1_async::TLS_HANDSHAKE_TIMEOUT, acceptor.accept(tcp_stream));
863 match handshake.await {
864 Err(_) => {} Ok(Err(e)) => eprintln!("TLS handshake failed: {}", e),
866 Ok(Ok(tls_stream)) => {
867 let server_conn = tls_stream.get_ref().1;
868 let sni = server_conn.server_name().map(|s| s.to_string());
869 let protocol = server_conn.alpn_protocol().map(|p| p.to_vec());
870
871 match protocol.as_deref() {
872 Some(b"h2") => {
873 if let Err(e) = crate::h2_server::handle_connection(tls_stream, peer_addr, sni, app).await {
874 eprintln!("H2 connection error: {}", e);
875 }
876 }
877 _ => {
878 crate::metrics::connection_open();
879 let result = http1_async::serve(tls_stream, peer_addr, sni, true, app).await;
880 crate::metrics::connection_close();
881 if let Err(e) = result {
882 crate::metrics::record_error();
883 eprintln!("H1 TLS error: {}", e);
884 }
885 }
886 }
887 }
888 }
889}
890
891#[cfg(feature = "http2")]
893async fn serve_plain_connection(
894 tcp_stream: tokio::net::TcpStream,
895 peer_addr: std::net::SocketAddr,
896 app: impl Application + Send + 'static + Clone,
897) {
898 let _ = tcp_stream.set_nodelay(true);
901 crate::metrics::connection_open();
902 let result = http1_async::serve(tcp_stream, peer_addr, None, false, app).await;
903 crate::metrics::connection_close();
904 if let Err(e) = result {
905 crate::metrics::record_error();
906 eprintln!("{}", e);
907 }
908}
909
910#[cfg(feature = "http2")]
913async fn accept_backoff(e: std::io::Error) {
914 eprintln!("TCP accept error: {}", e);
915 tokio::time::sleep(std::time::Duration::from_millis(50)).await;
916}
917
918#[cfg(feature = "http2")]
921async fn sigterm() {
922 #[cfg(unix)]
923 {
924 if let Ok(mut s) = tokio::signal::unix::signal(
925 tokio::signal::unix::SignalKind::terminate()
926 ) {
927 s.recv().await;
928 } else {
929 std::future::pending::<()>().await
930 }
931 }
932 #[cfg(not(unix))]
933 std::future::pending::<()>().await
934}
935
936#[cfg(feature = "http2")]
938async fn sighup() {
939 #[cfg(unix)]
940 {
941 if let Ok(mut s) = tokio::signal::unix::signal(
942 tokio::signal::unix::SignalKind::hangup()
943 ) {
944 s.recv().await;
945 } else {
946 std::future::pending::<()>().await
947 }
948 }
949 #[cfg(not(unix))]
950 std::future::pending::<()>().await
951}
952
953#[cfg(feature = "http2")]
960pub(crate) async fn bind_all_families(ip: &str, port: u16) -> Result<Vec<tokio::net::TcpListener>, String> {
961 use tokio::net::TcpListener;
962 if ip != "0.0.0.0" {
963 let addr = if ip.contains(':') { format!("[{ip}]:{port}") } else { format!("{ip}:{port}") };
964 return TcpListener::bind(&addr).await.map(|l| vec![l]).map_err(|e| format!("{addr}: {e}"));
965 }
966 let mut listeners = Vec::new();
967 let mut errors = Vec::new();
968 for addr in [format!("[::]:{port}"), format!("0.0.0.0:{port}")] {
969 match TcpListener::bind(&addr).await {
970 Ok(l) => listeners.push(l),
971 Err(e) => errors.push(format!("{addr}: {e}")),
972 }
973 }
974 if listeners.is_empty() {
975 return Err(errors.join("; "));
976 }
977 Ok(listeners)
978}
979
980#[cfg(feature = "http2")]
981impl Server {
982 pub async fn run_tls(
983 listener: TcpListener,
984 pool: ThreadPool,
985 app: impl Application + Send + 'static + Clone,
986 ) {
987 use crate::tls::create_tls_acceptor_from_vhosts;
988
989 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
990 .unwrap_or_default();
991 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
992 .unwrap_or_default();
993
994 if cert_path.is_empty() || key_path.is_empty() {
995 println!("No TLS certificate configured — serving plain HTTP/1.1.");
996 drop(pool);
997 Server::run_plain(listener, app).await;
998 return;
999 }
1000
1001 let vhosts = crate::entry_point::get_virtual_hosts();
1002 let mut tls_acceptor = match create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1003 Ok(a) => a,
1004 Err(e) => {
1005 eprintln!("TLS setup failed: {}", e);
1006 return;
1007 }
1008 };
1009
1010 #[cfg(unix)]
1011 if per_core::enabled() {
1012 println!("Listening for TLS connections (HTTP/1.1 + HTTP/2), per-core runtimes...");
1013 let (acceptor_tx, acceptor_rx) = tokio::sync::watch::channel(tls_acceptor);
1014 let accept_loop = move |listener: tokio::net::TcpListener, mut stop: tokio::sync::watch::Receiver<bool>| {
1015 let app = app.clone();
1016 let acceptor_rx = acceptor_rx.clone();
1017 async move {
1018 loop {
1019 tokio::select! {
1020 result = listener.accept() => match result {
1021 Ok((tcp_stream, peer_addr)) => {
1022 let acceptor = acceptor_rx.borrow().clone();
1023 tokio::spawn(serve_tls_connection(tcp_stream, peer_addr, acceptor, app.clone()));
1024 }
1025 Err(e) => accept_backoff(e).await,
1026 },
1027 _ = per_core::stopped(&mut stop) => break,
1028 }
1029 }
1030 }
1031 };
1032 Server::run_per_core(listener, accept_loop, move || {
1033 let vhosts = crate::entry_point::get_virtual_hosts();
1034 if let Ok(new_acceptor) = create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1035 let _ = acceptor_tx.send(new_acceptor);
1036 println!("[TLS] Certificates reloaded ({} virtual hosts).", vhosts.len());
1037 }
1038 })
1039 .await;
1040 return;
1041 }
1042
1043 listener
1044 .set_nonblocking(true)
1045 .expect("failed to set TCP listener to non-blocking");
1046 let tokio_listener = tokio::net::TcpListener::from_std(listener)
1047 .expect("failed to convert TCP listener to tokio");
1048
1049 println!("Listening for TLS connections (HTTP/1.1 + HTTP/2)...");
1050
1051 loop {
1052 tokio::select! {
1053 result = tokio_listener.accept() => {
1054 match result {
1055 Ok((tcp_stream, peer_addr)) => {
1056 tokio::spawn(serve_tls_connection(tcp_stream, peer_addr, tls_acceptor.clone(), app.clone()));
1057 }
1058 Err(e) => eprintln!("TCP accept error: {}", e),
1059 }
1060 }
1061 _ = tokio::signal::ctrl_c() => {
1062 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1063 println!("\nShutting down gracefully (SIGINT).");
1064 break;
1065 }
1066 _ = sigterm() => {
1067 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1068 println!("\nShutting down gracefully (SIGTERM).");
1069 break;
1070 }
1071 _ = sighup() => {
1072 crate::config_reload::reload();
1073 let vhosts = crate::entry_point::get_virtual_hosts();
1074 if let Ok(new_acceptor) = create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1075 tls_acceptor = new_acceptor;
1076 println!("[TLS] Certificates reloaded ({} virtual hosts).", vhosts.len());
1077 }
1078 }
1079 }
1080 }
1081 }
1082
1083 pub async fn run_plain(listener: TcpListener, app: impl Application + Send + 'static + Clone) {
1089 #[cfg(unix)]
1090 if per_core::enabled() {
1091 let accept_loop = move |listener: tokio::net::TcpListener, mut stop: tokio::sync::watch::Receiver<bool>| {
1092 let app = app.clone();
1093 async move {
1094 loop {
1095 tokio::select! {
1096 result = listener.accept() => match result {
1097 Ok((tcp_stream, peer_addr)) => {
1098 tokio::spawn(serve_plain_connection(tcp_stream, peer_addr, app.clone()));
1099 }
1100 Err(e) => accept_backoff(e).await,
1101 },
1102 _ = per_core::stopped(&mut stop) => break,
1103 }
1104 }
1105 }
1106 };
1107 Server::run_per_core(listener, accept_loop, || {}).await;
1108 return;
1109 }
1110
1111 listener
1112 .set_nonblocking(true)
1113 .expect("failed to set TCP listener to non-blocking");
1114 let tokio_listener = tokio::net::TcpListener::from_std(listener)
1115 .expect("failed to convert TCP listener to tokio");
1116
1117 loop {
1118 tokio::select! {
1119 result = tokio_listener.accept() => {
1120 match result {
1121 Ok((tcp_stream, peer_addr)) => {
1122 tokio::spawn(serve_plain_connection(tcp_stream, peer_addr, app.clone()));
1123 }
1124 Err(e) => accept_backoff(e).await,
1125 }
1126 }
1127 _ = tokio::signal::ctrl_c() => {
1128 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1129 println!("\nShutting down gracefully (SIGINT).");
1130 break;
1131 }
1132 _ = sigterm() => {
1133 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1134 println!("\nShutting down gracefully (SIGTERM).");
1135 break;
1136 }
1137 _ = sighup() => {
1138 crate::config_reload::reload();
1139 }
1140 }
1141 }
1142 }
1143
1144 #[cfg(unix)]
1149 async fn run_per_core<F, Fut>(listener: TcpListener, accept_loop: F, on_reload: impl Fn())
1150 where
1151 F: Fn(tokio::net::TcpListener, tokio::sync::watch::Receiver<bool>) -> Fut + Send + Clone + 'static,
1152 Fut: std::future::Future<Output = ()>,
1153 {
1154 let addr = match listener.local_addr() {
1155 Ok(a) => a,
1156 Err(e) => return eprintln!("per-core runtimes: {}", e),
1157 };
1158 drop(listener);
1160 let count = per_core::runtime_count();
1161 let (stop_tx, stop_rx) = tokio::sync::watch::channel(false);
1162 let handles = per_core::spawn(addr, count, stop_rx, accept_loop);
1163 println!("Started {} per-core runtimes on {}.", handles.len(), addr);
1164
1165 loop {
1166 tokio::select! {
1167 _ = tokio::signal::ctrl_c() => {
1168 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1169 println!("\nShutting down gracefully (SIGINT).");
1170 break;
1171 }
1172 _ = sigterm() => {
1173 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1174 println!("\nShutting down gracefully (SIGTERM).");
1175 break;
1176 }
1177 _ = sighup() => {
1178 crate::config_reload::reload();
1179 on_reload();
1180 }
1181 }
1182 }
1183 let _ = stop_tx.send(true);
1184 let _ = tokio::task::spawn_blocking(move || {
1185 for h in handles {
1186 let _ = h.join();
1187 }
1188 })
1189 .await;
1190 }
1191
1192 pub async fn run_redirect() {
1196 use std::env;
1197
1198 let cert_path = env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1199 .unwrap_or_default();
1200 if cert_path.is_empty() {
1201 return;
1202 }
1203
1204 let redirect_port_str = env::var(crate::entry_point::Config::RWS_CONFIG_HTTP_REDIRECT_PORT)
1205 .unwrap_or_default();
1206 if redirect_port_str.is_empty() {
1207 return;
1208 }
1209
1210 let redirect_port: u16 = match redirect_port_str.parse() {
1211 Ok(p) => p,
1212 Err(_) => {
1213 eprintln!("Invalid RWS_CONFIG_HTTP_REDIRECT_PORT: {}", redirect_port_str);
1214 return;
1215 }
1216 };
1217
1218 let (server_ip, server_port, _) = get_ip_port_thread_count();
1219 let listeners = match bind_all_families(&server_ip, redirect_port).await {
1220 Ok(l) => l,
1221 Err(e) => {
1222 eprintln!("HTTP redirect listener error on port {}: {}", redirect_port, e);
1223 return;
1224 }
1225 };
1226
1227 println!("HTTP→HTTPS redirect listening on http://{}:{}", server_ip, redirect_port);
1228 #[cfg(feature = "acme")]
1229 crate::acme::note_redirect_listener(redirect_port);
1230
1231 for listener in listeners {
1232 tokio::spawn(async move {
1233 loop {
1234 match listener.accept().await {
1235 Ok((stream, _peer)) => {
1236 tokio::spawn(Server::handle_redirect_connection(stream, server_port));
1237 }
1238 Err(e) => eprintln!("HTTP redirect accept error: {}", e),
1239 }
1240 }
1241 });
1242 }
1243
1244 loop {
1245 tokio::select! {
1246 _ = tokio::signal::ctrl_c() => {
1247 println!("\nShutting down HTTP redirect listener (SIGINT).");
1248 break;
1249 }
1250 _ = sigterm() => {
1251 println!("\nShutting down HTTP redirect listener (SIGTERM).");
1252 break;
1253 }
1254 _ = sighup() => {
1255 crate::config_reload::reload();
1256 }
1257 }
1258 }
1259 }
1260
1261 pub(crate) async fn handle_redirect_connection(mut stream: tokio::net::TcpStream, https_port: i32) {
1264 use tokio::io::{AsyncReadExt, AsyncWriteExt};
1265 let mut buf = vec![0u8; 4096];
1266 let n = match stream.read(&mut buf).await {
1267 Ok(n) => n,
1268 Err(_) => return,
1269 };
1270 let text = String::from_utf8_lossy(&buf[..n]);
1271
1272 let uri = text.lines()
1273 .next()
1274 .and_then(|line| line.split_whitespace().nth(1))
1275 .unwrap_or("/")
1276 .to_string();
1277
1278 #[cfg(feature = "acme")]
1281 if let Some(challenge) = crate::acme::challenge_http_response(&uri) {
1282 let _ = stream.write_all(challenge.as_bytes()).await;
1283 return;
1284 }
1285
1286 let host_header = text.lines()
1287 .find(|l| l.to_lowercase().starts_with("host:"))
1288 .map(|l| l[5..].trim().to_string());
1289
1290 let location = match host_header {
1291 Some(h) => {
1292 let h_no_port = if h.starts_with('[') {
1294 h.find(']')
1296 .map(|i| h[..=i].to_string())
1297 .unwrap_or(h.clone())
1298 } else {
1299 h.rfind(':')
1300 .map(|i| h[..i].to_string())
1301 .unwrap_or(h.clone())
1302 };
1303 if https_port == 443 {
1304 format!("https://{}{}", h_no_port, uri)
1305 } else {
1306 format!("https://{}:{}{}", h_no_port, https_port, uri)
1307 }
1308 }
1309 None => format!("https://localhost:{}{}", https_port, uri),
1310 };
1311
1312 let response = format!(
1313 "HTTP/1.1 301 Moved Permanently\r\nLocation: {}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n",
1314 location
1315 );
1316 let _ = stream.write_all(response.as_bytes()).await;
1317 }
1318
1319}
1320
1321#[cfg(feature = "http3")]
1322impl Server {
1323 pub async fn run_quic(
1324 app: impl Application + Send + 'static + Clone,
1325 ) {
1326 use crate::tls::create_quinn_server_config_from_vhosts;
1327 use crate::h3_handler;
1328
1329 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1330 .unwrap_or_default();
1331 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
1332 .unwrap_or_default();
1333
1334 if cert_path.is_empty() || key_path.is_empty() {
1335 return;
1336 }
1337
1338 let vhosts = crate::entry_point::get_virtual_hosts();
1339 let server_config = match create_quinn_server_config_from_vhosts(&vhosts, &cert_path, &key_path) {
1340 Ok(c) => c,
1341 Err(e) => {
1342 eprintln!("QUIC TLS setup failed: {}", e);
1343 return;
1344 }
1345 };
1346
1347 let (server_ip, server_port, _) = get_ip_port_thread_count();
1348 let bind_addr = format!("{}:{}", server_ip, server_port);
1349 let addr: std::net::SocketAddr = match bind_addr.parse() {
1350 Ok(a) => a,
1351 Err(e) => {
1352 eprintln!("Invalid QUIC bind address '{}': {}", bind_addr, e);
1353 return;
1354 }
1355 };
1356
1357 let endpoint = match quinn::Endpoint::server(server_config, addr) {
1358 Ok(e) => e,
1359 Err(e) => {
1360 eprintln!("QUIC endpoint error: {}", e);
1361 return;
1362 }
1363 };
1364
1365 println!("Listening for QUIC/HTTP3 on UDP {}:{}", server_ip, server_port);
1366
1367 loop {
1368 tokio::select! {
1369 maybe = endpoint.accept() => {
1370 match maybe {
1371 Some(incoming) => {
1372 let app = app.clone();
1373 tokio::spawn(async move {
1374 match incoming.await {
1375 Ok(conn) => {
1376 let peer_addr = conn.remote_address();
1377 if let Err(e) = h3_handler::handle_connection(conn, peer_addr, app).await {
1378 eprintln!("H3 connection error: {}", e);
1379 }
1380 }
1381 Err(e) => eprintln!("QUIC connection error: {}", e),
1382 }
1383 });
1384 }
1385 None => break,
1386 }
1387 }
1388 _ = tokio::signal::ctrl_c() => {
1389 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1390 println!("\nShutting down QUIC (SIGINT).");
1391 endpoint.close(0u32.into(), b"shutdown");
1392 break;
1393 }
1394 _ = sigterm() => {
1395 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1396 println!("\nShutting down QUIC (SIGTERM).");
1397 endpoint.close(0u32.into(), b"shutdown");
1398 break;
1399 }
1400 _ = sighup() => {
1401 crate::config_reload::reload();
1402 }
1403 }
1404 }
1405 }
1406}
1407
1408