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_compression(&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")]
920fn shutdown_requests() -> &'static tokio::sync::watch::Sender<bool> {
921 static REQUESTS: std::sync::OnceLock<tokio::sync::watch::Sender<bool>> = std::sync::OnceLock::new();
922 REQUESTS.get_or_init(|| tokio::sync::watch::channel(false).0)
923}
924
925#[cfg(feature = "http2")]
929pub fn request_shutdown() {
930 shutdown_requests().send_replace(true);
931}
932
933#[cfg(feature = "http2")]
936async fn sigterm() {
937 let requested = async {
938 let mut requests = shutdown_requests().subscribe();
939 let _ = requests.wait_for(|stop| *stop).await;
940 };
941 #[cfg(unix)]
942 {
943 if let Ok(mut s) = tokio::signal::unix::signal(
944 tokio::signal::unix::SignalKind::terminate()
945 ) {
946 tokio::select! {
947 _ = s.recv() => {}
948 _ = requested => {}
949 }
950 } else {
951 requested.await
952 }
953 }
954 #[cfg(not(unix))]
955 requested.await
956}
957
958#[cfg(feature = "http2")]
960async fn sighup() {
961 #[cfg(unix)]
962 {
963 if let Ok(mut s) = tokio::signal::unix::signal(
964 tokio::signal::unix::SignalKind::hangup()
965 ) {
966 s.recv().await;
967 } else {
968 std::future::pending::<()>().await
969 }
970 }
971 #[cfg(not(unix))]
972 std::future::pending::<()>().await
973}
974
975#[cfg(feature = "http2")]
982pub(crate) async fn bind_all_families(ip: &str, port: u16) -> Result<Vec<tokio::net::TcpListener>, String> {
983 use tokio::net::TcpListener;
984 if ip != "0.0.0.0" {
985 let addr = if ip.contains(':') { format!("[{ip}]:{port}") } else { format!("{ip}:{port}") };
986 return TcpListener::bind(&addr).await.map(|l| vec![l]).map_err(|e| format!("{addr}: {e}"));
987 }
988 let mut listeners = Vec::new();
989 let mut errors = Vec::new();
990 for addr in [format!("[::]:{port}"), format!("0.0.0.0:{port}")] {
991 match TcpListener::bind(&addr).await {
992 Ok(l) => listeners.push(l),
993 Err(e) => errors.push(format!("{addr}: {e}")),
994 }
995 }
996 if listeners.is_empty() {
997 return Err(errors.join("; "));
998 }
999 Ok(listeners)
1000}
1001
1002#[cfg(feature = "http2")]
1003impl Server {
1004 pub async fn run_tls(
1005 listener: TcpListener,
1006 pool: ThreadPool,
1007 app: impl Application + Send + 'static + Clone,
1008 ) {
1009 use crate::tls::create_tls_acceptor_from_vhosts;
1010
1011 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1012 .unwrap_or_default();
1013 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
1014 .unwrap_or_default();
1015
1016 if cert_path.is_empty() || key_path.is_empty() {
1017 println!("No TLS certificate configured — serving plain HTTP/1.1.");
1018 drop(pool);
1019 Server::run_plain(listener, app).await;
1020 return;
1021 }
1022
1023 let vhosts = crate::entry_point::get_virtual_hosts();
1024 let mut tls_acceptor = match create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1025 Ok(a) => a,
1026 Err(e) => {
1027 eprintln!("TLS setup failed: {}", e);
1028 return;
1029 }
1030 };
1031
1032 #[cfg(unix)]
1033 if per_core::enabled() {
1034 println!("Listening for TLS connections (HTTP/1.1 + HTTP/2), per-core runtimes...");
1035 let (acceptor_tx, acceptor_rx) = tokio::sync::watch::channel(tls_acceptor);
1036 let accept_loop = move |listener: tokio::net::TcpListener, mut stop: tokio::sync::watch::Receiver<bool>| {
1037 let app = app.clone();
1038 let acceptor_rx = acceptor_rx.clone();
1039 async move {
1040 loop {
1041 tokio::select! {
1042 result = listener.accept() => match result {
1043 Ok((tcp_stream, peer_addr)) => {
1044 let acceptor = acceptor_rx.borrow().clone();
1045 tokio::spawn(serve_tls_connection(tcp_stream, peer_addr, acceptor, app.clone()));
1046 }
1047 Err(e) => accept_backoff(e).await,
1048 },
1049 _ = per_core::stopped(&mut stop) => break,
1050 }
1051 }
1052 }
1053 };
1054 Server::run_per_core(listener, accept_loop, move || {
1055 let vhosts = crate::entry_point::get_virtual_hosts();
1056 if let Ok(new_acceptor) = create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1057 let _ = acceptor_tx.send(new_acceptor);
1058 println!("[TLS] Certificates reloaded ({} virtual hosts).", vhosts.len());
1059 }
1060 })
1061 .await;
1062 return;
1063 }
1064
1065 listener
1066 .set_nonblocking(true)
1067 .expect("failed to set TCP listener to non-blocking");
1068 let tokio_listener = tokio::net::TcpListener::from_std(listener)
1069 .expect("failed to convert TCP listener to tokio");
1070
1071 println!("Listening for TLS connections (HTTP/1.1 + HTTP/2)...");
1072
1073 loop {
1074 tokio::select! {
1075 result = tokio_listener.accept() => {
1076 match result {
1077 Ok((tcp_stream, peer_addr)) => {
1078 tokio::spawn(serve_tls_connection(tcp_stream, peer_addr, tls_acceptor.clone(), app.clone()));
1079 }
1080 Err(e) => eprintln!("TCP accept error: {}", e),
1081 }
1082 }
1083 _ = tokio::signal::ctrl_c() => {
1084 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1085 println!("\nShutting down gracefully (SIGINT).");
1086 break;
1087 }
1088 _ = sigterm() => {
1089 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1090 println!("\nShutting down gracefully (SIGTERM).");
1091 break;
1092 }
1093 _ = sighup() => {
1094 crate::config_reload::reload();
1095 let vhosts = crate::entry_point::get_virtual_hosts();
1096 if let Ok(new_acceptor) = create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1097 tls_acceptor = new_acceptor;
1098 println!("[TLS] Certificates reloaded ({} virtual hosts).", vhosts.len());
1099 }
1100 }
1101 }
1102 }
1103 }
1104
1105 pub async fn run_plain(listener: TcpListener, app: impl Application + Send + 'static + Clone) {
1111 #[cfg(unix)]
1112 if per_core::enabled() {
1113 let accept_loop = move |listener: tokio::net::TcpListener, mut stop: tokio::sync::watch::Receiver<bool>| {
1114 let app = app.clone();
1115 async move {
1116 loop {
1117 tokio::select! {
1118 result = listener.accept() => match result {
1119 Ok((tcp_stream, peer_addr)) => {
1120 tokio::spawn(serve_plain_connection(tcp_stream, peer_addr, app.clone()));
1121 }
1122 Err(e) => accept_backoff(e).await,
1123 },
1124 _ = per_core::stopped(&mut stop) => break,
1125 }
1126 }
1127 }
1128 };
1129 Server::run_per_core(listener, accept_loop, || {}).await;
1130 return;
1131 }
1132
1133 listener
1134 .set_nonblocking(true)
1135 .expect("failed to set TCP listener to non-blocking");
1136 let tokio_listener = tokio::net::TcpListener::from_std(listener)
1137 .expect("failed to convert TCP listener to tokio");
1138
1139 loop {
1140 tokio::select! {
1141 result = tokio_listener.accept() => {
1142 match result {
1143 Ok((tcp_stream, peer_addr)) => {
1144 tokio::spawn(serve_plain_connection(tcp_stream, peer_addr, app.clone()));
1145 }
1146 Err(e) => accept_backoff(e).await,
1147 }
1148 }
1149 _ = tokio::signal::ctrl_c() => {
1150 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1151 println!("\nShutting down gracefully (SIGINT).");
1152 break;
1153 }
1154 _ = sigterm() => {
1155 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1156 println!("\nShutting down gracefully (SIGTERM).");
1157 break;
1158 }
1159 _ = sighup() => {
1160 crate::config_reload::reload();
1161 }
1162 }
1163 }
1164 }
1165
1166 #[cfg(unix)]
1171 async fn run_per_core<F, Fut>(listener: TcpListener, accept_loop: F, on_reload: impl Fn())
1172 where
1173 F: Fn(tokio::net::TcpListener, tokio::sync::watch::Receiver<bool>) -> Fut + Send + Clone + 'static,
1174 Fut: std::future::Future<Output = ()>,
1175 {
1176 let addr = match listener.local_addr() {
1177 Ok(a) => a,
1178 Err(e) => return eprintln!("per-core runtimes: {}", e),
1179 };
1180 drop(listener);
1182 let count = per_core::runtime_count();
1183 let (stop_tx, stop_rx) = tokio::sync::watch::channel(false);
1184 let handles = per_core::spawn(addr, count, stop_rx, accept_loop);
1185 println!("Started {} per-core runtimes on {}.", handles.len(), addr);
1186
1187 loop {
1188 tokio::select! {
1189 _ = tokio::signal::ctrl_c() => {
1190 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1191 println!("\nShutting down gracefully (SIGINT).");
1192 break;
1193 }
1194 _ = sigterm() => {
1195 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1196 println!("\nShutting down gracefully (SIGTERM).");
1197 break;
1198 }
1199 _ = sighup() => {
1200 crate::config_reload::reload();
1201 on_reload();
1202 }
1203 }
1204 }
1205 let _ = stop_tx.send(true);
1206 let _ = tokio::task::spawn_blocking(move || {
1207 for h in handles {
1208 let _ = h.join();
1209 }
1210 })
1211 .await;
1212 }
1213
1214 pub async fn run_redirect() {
1218 use std::env;
1219
1220 let cert_path = env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1221 .unwrap_or_default();
1222 if cert_path.is_empty() {
1223 return;
1224 }
1225
1226 let redirect_port_str = env::var(crate::entry_point::Config::RWS_CONFIG_HTTP_REDIRECT_PORT)
1227 .unwrap_or_default();
1228 if redirect_port_str.is_empty() {
1229 return;
1230 }
1231
1232 let redirect_port: u16 = match redirect_port_str.parse() {
1233 Ok(p) => p,
1234 Err(_) => {
1235 eprintln!("Invalid RWS_CONFIG_HTTP_REDIRECT_PORT: {}", redirect_port_str);
1236 return;
1237 }
1238 };
1239
1240 let (server_ip, server_port, _) = get_ip_port_thread_count();
1241 let listeners = match bind_all_families(&server_ip, redirect_port).await {
1242 Ok(l) => l,
1243 Err(e) => {
1244 eprintln!("HTTP redirect listener error on port {}: {}", redirect_port, e);
1245 return;
1246 }
1247 };
1248
1249 println!("HTTP→HTTPS redirect listening on http://{}:{}", server_ip, redirect_port);
1250 #[cfg(feature = "acme")]
1251 crate::acme::note_redirect_listener(redirect_port);
1252
1253 for listener in listeners {
1254 tokio::spawn(async move {
1255 loop {
1256 match listener.accept().await {
1257 Ok((stream, _peer)) => {
1258 tokio::spawn(Server::handle_redirect_connection(stream, server_port));
1259 }
1260 Err(e) => eprintln!("HTTP redirect accept error: {}", e),
1261 }
1262 }
1263 });
1264 }
1265
1266 loop {
1267 tokio::select! {
1268 _ = tokio::signal::ctrl_c() => {
1269 println!("\nShutting down HTTP redirect listener (SIGINT).");
1270 break;
1271 }
1272 _ = sigterm() => {
1273 println!("\nShutting down HTTP redirect listener (SIGTERM).");
1274 break;
1275 }
1276 _ = sighup() => {
1277 crate::config_reload::reload();
1278 }
1279 }
1280 }
1281 }
1282
1283 pub(crate) async fn handle_redirect_connection(mut stream: tokio::net::TcpStream, https_port: i32) {
1286 use tokio::io::{AsyncReadExt, AsyncWriteExt};
1287 let mut buf = vec![0u8; 4096];
1288 let n = match stream.read(&mut buf).await {
1289 Ok(n) => n,
1290 Err(_) => return,
1291 };
1292 let text = String::from_utf8_lossy(&buf[..n]);
1293
1294 let uri = text.lines()
1295 .next()
1296 .and_then(|line| line.split_whitespace().nth(1))
1297 .unwrap_or("/")
1298 .to_string();
1299
1300 #[cfg(feature = "acme")]
1303 if let Some(challenge) = crate::acme::challenge_http_response(&uri) {
1304 let _ = stream.write_all(challenge.as_bytes()).await;
1305 return;
1306 }
1307
1308 let host_header = text.lines()
1309 .find(|l| l.to_lowercase().starts_with("host:"))
1310 .map(|l| l[5..].trim().to_string());
1311
1312 let location = match host_header {
1313 Some(h) => {
1314 let h_no_port = if h.starts_with('[') {
1316 h.find(']')
1318 .map(|i| h[..=i].to_string())
1319 .unwrap_or(h.clone())
1320 } else {
1321 h.rfind(':')
1322 .map(|i| h[..i].to_string())
1323 .unwrap_or(h.clone())
1324 };
1325 if https_port == 443 {
1326 format!("https://{}{}", h_no_port, uri)
1327 } else {
1328 format!("https://{}:{}{}", h_no_port, https_port, uri)
1329 }
1330 }
1331 None => format!("https://localhost:{}{}", https_port, uri),
1332 };
1333
1334 let response = format!(
1335 "HTTP/1.1 301 Moved Permanently\r\nLocation: {}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n",
1336 location
1337 );
1338 let _ = stream.write_all(response.as_bytes()).await;
1339 }
1340
1341}
1342
1343#[cfg(feature = "http3")]
1344impl Server {
1345 pub async fn run_quic(
1346 app: impl Application + Send + 'static + Clone,
1347 ) {
1348 use crate::tls::create_quinn_server_config_from_vhosts;
1349 use crate::h3_handler;
1350
1351 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1352 .unwrap_or_default();
1353 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
1354 .unwrap_or_default();
1355
1356 if cert_path.is_empty() || key_path.is_empty() {
1357 return;
1358 }
1359
1360 let vhosts = crate::entry_point::get_virtual_hosts();
1361 let server_config = match create_quinn_server_config_from_vhosts(&vhosts, &cert_path, &key_path) {
1362 Ok(c) => c,
1363 Err(e) => {
1364 eprintln!("QUIC TLS setup failed: {}", e);
1365 return;
1366 }
1367 };
1368
1369 let (server_ip, server_port, _) = get_ip_port_thread_count();
1370 let bind_addr = format!("{}:{}", server_ip, server_port);
1371 let addr: std::net::SocketAddr = match bind_addr.parse() {
1372 Ok(a) => a,
1373 Err(e) => {
1374 eprintln!("Invalid QUIC bind address '{}': {}", bind_addr, e);
1375 return;
1376 }
1377 };
1378
1379 let endpoint = match quinn::Endpoint::server(server_config, addr) {
1380 Ok(e) => e,
1381 Err(e) => {
1382 eprintln!("QUIC endpoint error: {}", e);
1383 return;
1384 }
1385 };
1386
1387 println!("Listening for QUIC/HTTP3 on UDP {}:{}", server_ip, server_port);
1388
1389 loop {
1390 tokio::select! {
1391 maybe = endpoint.accept() => {
1392 match maybe {
1393 Some(incoming) => {
1394 let app = app.clone();
1395 tokio::spawn(async move {
1396 match incoming.await {
1397 Ok(conn) => {
1398 let peer_addr = conn.remote_address();
1399 if let Err(e) = h3_handler::handle_connection(conn, peer_addr, app).await {
1400 eprintln!("H3 connection error: {}", e);
1401 }
1402 }
1403 Err(e) => eprintln!("QUIC connection error: {}", e),
1404 }
1405 });
1406 }
1407 None => break,
1408 }
1409 }
1410 _ = tokio::signal::ctrl_c() => {
1411 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1412 println!("\nShutting down QUIC (SIGINT).");
1413 endpoint.close(0u32.into(), b"shutdown");
1414 break;
1415 }
1416 _ = sigterm() => {
1417 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1418 println!("\nShutting down QUIC (SIGTERM).");
1419 endpoint.close(0u32.into(), b"shutdown");
1420 break;
1421 }
1422 _ = sighup() => {
1423 crate::config_reload::reload();
1424 }
1425 }
1426 }
1427 }
1428}
1429
1430