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;
26pub mod proxy_protocol;
27
28#[cfg(not(target_arch = "wasm32"))]
34use std::io::prelude::*;
35#[cfg(not(target_arch = "wasm32"))]
36use std::borrow::Borrow;
37#[cfg(not(target_arch = "wasm32"))]
38use std::net::{IpAddr, SocketAddr, TcpListener};
39#[cfg(not(target_arch = "wasm32"))]
40use std::str::FromStr;
41#[cfg(not(target_arch = "wasm32"))]
42use std::time::Duration;
43
44#[cfg(not(target_arch = "wasm32"))]
45use crate::request::{METHOD, Request};
46#[cfg(not(target_arch = "wasm32"))]
47use crate::response::{Response, STATUS_CODE_REASON_PHRASE};
48#[cfg(not(target_arch = "wasm32"))]
49use crate::app::App;
50#[cfg(not(target_arch = "wasm32"))]
51use crate::application::Application;
52#[cfg(not(target_arch = "wasm32"))]
53use crate::entry_point::{bootstrap, get_ip_port_thread_count, get_request_allocation_size, set_default_values};
54#[cfg(not(target_arch = "wasm32"))]
55use crate::header::Header;
56#[cfg(not(target_arch = "wasm32"))]
57use crate::log::Log;
58#[cfg(not(target_arch = "wasm32"))]
59use crate::mime_type::MimeType;
60#[cfg(not(target_arch = "wasm32"))]
61use crate::range::{ContentRange, Range};
62#[cfg(not(target_arch = "wasm32"))]
63use crate::symbol::SYMBOL;
64#[cfg(not(target_arch = "wasm32"))]
65use crate::thread_pool::ThreadPool;
66
67#[cfg(not(target_arch = "wasm32"))]
68pub const REQUEST_HEAD_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30);
73
74pub struct Server {}
75#[cfg(not(target_arch = "wasm32"))]
76impl Server {
77 pub fn process_request(mut stream: impl Read + Write + Unpin, peer_addr: SocketAddr) -> Vec<u8> {
78 let request_allocation_size = get_request_allocation_size();
79 let mut buffer = vec![0; request_allocation_size as usize];
80 let boxed_read = stream.read(&mut buffer);
81 if boxed_read.is_err() {
82 let message = boxed_read.err().unwrap().to_string();
83 eprintln!("unable to read TCP stream {}", &message);
84
85 let raw_response = Server::bad_request_response(message);
86 let boxed_stream = stream.write(raw_response.borrow());
87 if boxed_stream.is_ok() {
88 stream.flush().unwrap();
89 };
90 return raw_response;
91 }
92
93 boxed_read.unwrap();
94 let request : &[u8] = &buffer;
95
96 let boxed_request = Request::parse_request(request);
101 if boxed_request.is_err() {
102 let message = boxed_request.err().unwrap();
103 eprintln!("unable to parse request: {}", &message);
104
105 let raw_response = Server::bad_request_response(message);
106 let boxed_stream = stream.write(raw_response.borrow());
107 if boxed_stream.is_ok() {
108 stream.flush().unwrap();
109 };
110 return raw_response;
111 }
112
113
114 let request: Request = boxed_request.unwrap();
115 let (response, request) = App::handle_request(request);
116
117
118 let log_request_response = Log::combined(&request, &response, &peer_addr);
119 println!("{}", log_request_response);
120 let raw_response = Response::generate_response(response, request);
121
122 let boxed_stream = stream.write(raw_response.borrow());
123 if boxed_stream.is_ok() {
124 stream.flush().unwrap();
125 };
126
127 raw_response
128 }
129
130 pub fn bad_request_response(message: String) -> Vec<u8> {
131 let error_request = Request {
132 method: METHOD.get.to_string(),
133 request_uri: "".to_string(),
134 http_version: "".to_string(),
135 headers: vec![],
136 body: Default::default(),
137 };
138
139 let size = message.chars().count() as u64;
140 let content_range = ContentRange {
141 unit: Range::BYTES.to_string(),
142 range: Range { start: 0, end: size },
143 size: size.to_string(),
144 body: Vec::from(message.as_bytes()),
145 content_type: MimeType::TEXT_PLAIN.to_string(),
146 };
147
148 let header_list = Header::get_header_list(&error_request);
149 let error_response: Response = Response::get_response(
150 STATUS_CODE_REASON_PHRASE.n400_bad_request,
151 Some(header_list),
152 Some(vec![content_range])
153 );
154
155 let response = Response::generate_response(error_response, error_request);
156 return response;
157 }
158
159 pub fn payload_too_large_response(message: String) -> Vec<u8> {
165 let error_request = Request {
166 method: METHOD.get.to_string(),
167 request_uri: "".to_string(),
168 http_version: "".to_string(),
169 headers: vec![],
170 body: Default::default(),
171 };
172
173 let size = message.chars().count() as u64;
174 let content_range = ContentRange {
175 unit: Range::BYTES.to_string(),
176 range: Range { start: 0, end: size },
177 size: size.to_string(),
178 body: Vec::from(message.as_bytes()),
179 content_type: MimeType::TEXT_PLAIN.to_string(),
180 };
181
182 let mut header_list = Header::get_header_list(&error_request);
183 header_list.push(Header { name: Header::_CONNECTION.into(), value: "close".into() });
184 let error_response: Response = Response::get_response(
185 STATUS_CODE_REASON_PHRASE.n413_payload_too_large,
186 Some(header_list),
187 Some(vec![content_range])
188 );
189
190 Response::generate_response(error_response, error_request)
191 }
192
193 pub fn header_fields_too_large_response() -> Vec<u8> {
197 Server::closing_error_response(
198 STATUS_CODE_REASON_PHRASE.n431_request_header_fields_too_large,
199 format!("431 Request Header Fields Too Large: the request head exceeds {} bytes", framing::MAX_HEAD_SIZE),
200 )
201 }
202
203 pub fn request_timeout_response() -> Vec<u8> {
207 Server::closing_error_response(
208 STATUS_CODE_REASON_PHRASE.n408_request_timeout,
209 format!("408 Request Timeout: the request head took longer than {} s", REQUEST_HEAD_TIMEOUT.as_secs()),
210 )
211 }
212
213 fn closing_error_response(status: &'static crate::response::StatusCodeReasonPhrase, message: String) -> Vec<u8> {
215 let error_request = Request {
216 method: METHOD.get.to_string(),
217 request_uri: "".to_string(),
218 http_version: "".to_string(),
219 headers: vec![],
220 body: Default::default(),
221 };
222
223 let size = message.chars().count() as u64;
224 let content_range = ContentRange {
225 unit: Range::BYTES.to_string(),
226 range: Range { start: 0, end: size },
227 size: size.to_string(),
228 body: Vec::from(message.as_bytes()),
229 content_type: MimeType::TEXT_PLAIN.to_string(),
230 };
231
232 let mut header_list = Header::get_header_list(&error_request);
233 header_list.push(Header { name: Header::_CONNECTION.into(), value: "close".into() });
234 let error_response: Response = Response::get_response(status, Some(header_list), Some(vec![content_range]));
235
236 Response::generate_response(error_response, error_request)
237 }
238
239 pub fn continue_response() -> Vec<u8> {
245 let dummy_request = Request {
246 method: METHOD.get.to_string(),
247 request_uri: "".to_string(),
248 http_version: "".to_string(),
249 headers: vec![],
250 body: Default::default(),
251 };
252 let response = Response::get_response(STATUS_CODE_REASON_PHRASE.n100_continue, None, None);
253 Response::generate_response(response, dummy_request)
254 }
255
256 pub fn expectation_failed_response(message: String) -> Vec<u8> {
261 let error_request = Request {
262 method: METHOD.get.to_string(),
263 request_uri: "".to_string(),
264 http_version: "".to_string(),
265 headers: vec![],
266 body: Default::default(),
267 };
268
269 let size = message.chars().count() as u64;
270 let content_range = ContentRange {
271 unit: Range::BYTES.to_string(),
272 range: Range { start: 0, end: size },
273 size: size.to_string(),
274 body: Vec::from(message.as_bytes()),
275 content_type: MimeType::TEXT_PLAIN.to_string(),
276 };
277
278 let mut header_list = Header::get_header_list(&error_request);
279 header_list.push(Header { name: Header::_CONNECTION.into(), value: "close".into() });
280 let error_response: Response = Response::get_response(
281 STATUS_CODE_REASON_PHRASE.n417_expectation_failed,
282 Some(header_list),
283 Some(vec![content_range])
284 );
285
286 Response::generate_response(error_response, error_request)
287 }
288
289 pub fn process(stream: impl Read + Write + Unpin,
290 connection: ConnectionInfo,
291 app: impl Application) -> Result<(), String> {
292 Self::process_upgradable(stream, connection, app, |_| None)
294 }
295
296 fn process_upgradable<S: Read + Write + Unpin>(
300 mut stream: S,
301 connection: ConnectionInfo,
302 app: impl Application,
303 split: impl Fn(&mut S) -> Option<(Box<dyn Read + Send>, Box<dyn Write + Send>)>,
304 ) -> Result<(), String> {
305
306 let request_allocation_size = connection.request_size;
307 let client = connection.client.clone();
308 let client_addr = SocketAddr::new(IpAddr::from_str(client.ip.as_str()).unwrap(), client.port as u16);
309
310 let max_body_size = crate::entry_point::get_max_body_size();
311
312 let mut pending: Vec<u8> = Vec::new();
315 let mut read_buffer = vec![0u8; request_allocation_size as usize];
316
317 'session: loop {
318 let mut head_started: Option<std::time::Instant> = None;
323 let head_len = loop {
324 framing::skip_leading_empty_lines(&mut pending);
325 match framing::scan_head(&pending) {
326 framing::HeadScan::Complete(n) => break Some(n),
327 framing::HeadScan::TooLarge => {
328 let _ = stream.write_all(&Server::header_fields_too_large_response());
329 let _ = stream.flush();
330 return Err("request head too large".to_string());
331 }
332 framing::HeadScan::Incomplete => {}
333 }
334 if !pending.is_empty() && head_started.is_none() {
335 head_started = Some(std::time::Instant::now());
336 }
337 match stream.read(&mut read_buffer) {
338 Ok(0) | Err(_) => break None,
340 Ok(n) => pending.extend_from_slice(&read_buffer[..n]),
341 }
342 let started = *head_started.get_or_insert_with(std::time::Instant::now);
343 if started.elapsed() > REQUEST_HEAD_TIMEOUT && framing::scan_head(&pending) == framing::HeadScan::Incomplete {
344 let _ = stream.write_all(&Server::request_timeout_response());
345 let _ = stream.flush();
346 return Err("request head timed out".to_string());
347 }
348 };
349 let Some(head_len) = head_len else { break };
350
351 let parsed = Request::parse(&pending[..head_len])
352 .and_then(|request| framing::validate_head(&pending[..head_len], &request).map(|_| request))
353 .and_then(|request| framing::body_framing(&request).map(|f| (request, f)));
354 pending.drain(..head_len);
355 let (mut request, body_framing) = match parsed {
356 Ok(parsed) => parsed,
357 Err(message) => {
358 let _ = stream.write_all(&Server::bad_request_response(message.clone()));
359 let _ = stream.flush();
360 return Err(message);
361 }
362 };
363
364 let expects_continue = match request.header(Header::_EXPECT) {
368 Some(h) if h.value.trim().eq_ignore_ascii_case("100-continue") => true,
369 Some(h) => {
370 let raw_response = Server::expectation_failed_response(format!(
371 "417 Expectation Failed: unsupported Expect value '{}'", h.value.trim()
372 ));
373 let _ = stream.write_all(&raw_response);
374 let _ = stream.flush();
375 break;
376 }
377 None => false,
378 };
379
380 match body_framing {
381 framing::BodyFraming::None => {}
382 framing::BodyFraming::Length(declared_len) => {
383 if max_body_size > 0 && declared_len > max_body_size {
384 let raw_response = Server::payload_too_large_response(format!(
385 "413 Payload Too Large: declared Content-Length {} exceeds the {} byte limit",
386 declared_len, max_body_size
387 ));
388 let _ = stream.write_all(&raw_response);
389 let _ = stream.flush();
390 break;
391 }
392
393 if expects_continue && (pending.len() as u64) < declared_len {
396 if stream.write_all(&Server::continue_response()).and_then(|_| stream.flush()).is_err() {
397 break;
398 }
399 }
400
401 while (pending.len() as u64) < declared_len {
402 match stream.read(&mut read_buffer) {
403 Ok(0) | Err(_) => break 'session, Ok(k) => pending.extend_from_slice(&read_buffer[..k]),
405 }
406 }
407 request.body = pending.drain(..declared_len as usize).collect::<Vec<u8>>().into();
408 }
409 framing::BodyFraming::Chunked => {
410 if expects_continue && pending.is_empty() {
411 if stream.write_all(&Server::continue_response()).and_then(|_| stream.flush()).is_err() {
412 break;
413 }
414 }
415
416 let mut decoder = framing::ChunkedBody::new(max_body_size);
417 loop {
418 match decoder.feed(&pending) {
419 Ok((consumed, done)) => {
420 pending.drain(..consumed);
421 if done { break; }
422 }
423 Err(framing::ChunkError::TooLarge) => {
424 let raw_response = Server::payload_too_large_response(format!(
425 "413 Payload Too Large: chunked body exceeds the {} byte limit", max_body_size
426 ));
427 let _ = stream.write_all(&raw_response);
428 let _ = stream.flush();
429 break 'session;
430 }
431 Err(framing::ChunkError::Malformed(message)) => {
432 let _ = stream.write_all(&Server::bad_request_response(message.clone()));
433 let _ = stream.flush();
434 return Err(message);
435 }
436 }
437 match stream.read(&mut read_buffer) {
438 Ok(0) | Err(_) => break 'session,
439 Ok(k) => pending.extend_from_slice(&read_buffer[..k]),
440 }
441 }
442 request.body = decoder.body.into();
443 }
444 }
445
446 let keep_alive = framing::keep_alive(&request);
447
448 let started = std::time::Instant::now();
449 let result = if crate::early_hints::http1_wanted(&request) {
452 let hints: std::sync::Arc<std::sync::Mutex<Vec<Vec<String>>>> = Default::default();
453 let queue = std::sync::Arc::clone(&hints);
454 let sink = crate::early_hints::Sink::new(move |links| queue.lock().unwrap_or_else(|e| e.into_inner()).push(links));
455 let result = crate::early_hints::with_sink(Some(sink), || app.execute(&request, &connection));
456 for links in std::mem::take(&mut *hints.lock().unwrap_or_else(|e| e.into_inner())) {
457 if stream.write_all(&crate::early_hints::http1_head(&links)).is_err() {
458 return Err("client closed the connection".to_string());
459 }
460 }
461 result
462 } else {
463 app.execute(&request, &connection)
464 };
465 let mut response = match result {
466 Ok(r) => r,
467 Err(message) => {
468 crate::metrics::http::observe(&request.method, 400, false, &request.http_version, started);
469 let raw_response = Server::bad_request_response(message.clone());
470 let boxed_stream = stream.write(raw_response.borrow());
471 if boxed_stream.is_ok() { stream.flush().unwrap(); }
472 return Err(message);
473 }
474 };
475
476 crate::metrics::record_request();
477 crate::metrics::http::observe(&request.method, response.status_code, false, &request.http_version, started);
478 if let Some(upgrade) = crate::websocket::take_upgrade(&mut response) {
481 let Some((reader, writer)) = split(&mut stream) else {
482 let _ = stream.write_all(b"HTTP/1.1 500 Internal Server Error\r\nContent-Length: 0\r\nConnection: close\r\n\r\n");
483 let _ = stream.flush();
484 return Err("WebSocket upgrade on a connection that can't be handed over".to_string());
485 };
486 Log::log_access(&request, &response, &client_addr);
487 stream.write_all(&crate::websocket::upgrade_head(&response)).and_then(|_| stream.flush()).map_err(|e| e.to_string())?;
488 let reader = std::io::Cursor::new(std::mem::take(&mut pending)).chain(reader);
489 std::thread::spawn(move || upgrade.run(Box::new(reader), writer));
490 return Ok(());
491 }
492 crate::compression::apply_compression(&request, &mut response);
493 response.drop_content_for_status();
494
495 response.headers.push(Header {
496 name: Header::_CONNECTION.into(),
497 value: if keep_alive { "keep-alive".into() } else { "close".into() },
498 });
499
500 Log::log_access(&request, &response, &client_addr);
501
502 if let Some(reader) = response.stream_pipe.take() {
503 if let Err(e) = Server::pipe_stream(&mut stream, response, request, reader) {
504 return Err(e);
505 }
506 } else if let Some(ref filepath) = response.stream_file.clone() {
507 if let Err(e) = Server::write_chunked_file(&mut stream, response, request, filepath) {
508 return Err(e);
509 }
510 } else {
511 let raw_response = Response::generate_response(response, request);
512 if let Err(e) = stream.write_all(raw_response.borrow()) {
514 return Err(e.to_string());
515 }
516 stream.flush().unwrap();
517 }
518
519 if !keep_alive { break; }
520 }
521
522 Ok(())
523 }
524
525 pub(crate) fn write_chunked_file(
528 stream: &mut impl Write,
529 response: Response,
530 request: Request,
531 filepath: &str,
532 ) -> Result<(), String> {
533 use std::fs::File;
534 use std::io::Read as _;
535
536 let (head, chunked) = Server::stream_file_head(response);
537 stream.write_all(&head).map_err(|e| e.to_string())?;
538
539 if request.method != METHOD.head {
540 let mut file = File::open(filepath).map_err(|e| e.to_string())?;
541 let mut buf = vec![0u8; 65536];
542 loop {
543 let n = file.read(&mut buf).map_err(|e| e.to_string())?;
544 if n == 0 { break; }
545 if chunked {
546 stream.write_all(format!("{:x}\r\n", n).as_bytes()).map_err(|e| e.to_string())?;
548 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
549 stream.write_all(b"\r\n").map_err(|e| e.to_string())?;
550 } else {
551 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
552 }
553 }
554 if chunked {
555 stream.write_all(b"0\r\n\r\n").map_err(|e| e.to_string())?;
557 }
558 }
559
560 stream.flush().map_err(|e| e.to_string())
561 }
562
563 pub(crate) fn stream_file_head(mut response: Response) -> (Vec<u8>, bool) {
570 let chunked = !response.headers.iter().any(|h| h.name.eq_ignore_ascii_case(Header::_CONTENT_LENGTH));
571 if chunked {
572 response.headers.push(Header {
573 name: Header::_TRANSFER_ENCODING.into(),
574 value: "chunked".into(),
575 });
576 }
577
578 let status = [
580 response.http_version.clone(),
581 response.status_code.to_string(),
582 Header::single_line(&response.reason_phrase).into_owned(),
583 ].join(SYMBOL.whitespace);
584
585 let mut headers_str = SYMBOL.new_line_carriage_return.to_string();
586 for header in &response.headers {
587 headers_str.push_str(&Header::single_line(&header.name));
588 headers_str.push_str(Header::NAME_VALUE_SEPARATOR);
589 headers_str.push_str(&Header::single_line(&header.value));
590 headers_str.push_str(SYMBOL.new_line_carriage_return);
591 }
592 let head = format!("{}{}{}", status, headers_str, SYMBOL.new_line_carriage_return);
593 (head.into_bytes(), chunked)
594 }
595
596 pub(crate) fn pipe_stream(
604 stream: &mut impl Write,
605 mut response: Response,
606 request: Request,
607 mut reader: Box<dyn std::io::Read + Send>,
608 ) -> Result<(), String> {
609 let backend_is_chunked = response.headers.iter().any(|h| {
613 h.name.eq_ignore_ascii_case("transfer-encoding")
614 && h.value.to_lowercase().contains("chunked")
615 });
616
617 response.headers.retain(|h| !h.name.eq_ignore_ascii_case("content-length"));
618 if !backend_is_chunked {
619 response.headers.push(Header {
620 name: Header::_TRANSFER_ENCODING.into(),
621 value: "chunked".into(),
622 });
623 }
624
625 let status = [
626 response.http_version.clone(),
627 response.status_code.to_string(),
628 Header::single_line(&response.reason_phrase).into_owned(),
629 ].join(SYMBOL.whitespace);
630
631 let mut head = format!("{}\r\n", status);
632 for header in &response.headers {
633 head.push_str(&Header::single_line(&header.name));
634 head.push_str(Header::NAME_VALUE_SEPARATOR);
635 head.push_str(&Header::single_line(&header.value));
636 head.push_str(SYMBOL.new_line_carriage_return);
637 }
638 head.push_str(SYMBOL.new_line_carriage_return);
639 stream.write_all(head.as_bytes()).map_err(|e| e.to_string())?;
640
641 if request.method != METHOD.head {
642 let mut buf = [0u8; 8192];
643 if backend_is_chunked {
644 loop {
647 match reader.read(&mut buf) {
648 Ok(0) | Err(_) => break,
649 Ok(n) => {
650 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
651 stream.flush().map_err(|e| e.to_string())?;
652 }
653 }
654 }
655 } else {
656 loop {
660 match reader.read(&mut buf) {
661 Ok(0) | Err(_) => break,
662 Ok(n) => {
663 stream
664 .write_all(format!("{:x}\r\n", n).as_bytes())
665 .map_err(|e| e.to_string())?;
666 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
667 stream.write_all(b"\r\n").map_err(|e| e.to_string())?;
668 stream.flush().map_err(|e| e.to_string())?;
669 }
670 }
671 }
672 stream.write_all(b"0\r\n\r\n").map_err(|e| e.to_string())?;
673 }
674 }
675
676 stream.flush().map_err(|e| e.to_string())
677 }
678
679 pub fn setup() -> Result<(TcpListener, ThreadPool), String> {
682 let info = Log::info("Rust Web Server");
683 println!("{}", info);
684
685 println!("Every setting: rws --help, or https://rws8.tech/docs/configuration/env-vars/\n");
688
689
690 println!("RWS Configuration Start: \n");
691
692 set_default_values();
693 bootstrap();
694
695 #[cfg(feature = "secrets")]
696 crate::secrets::resolve_env_vars().map_err(|e| e.to_string())?;
697
698 println!("\nRWS Configuration End\n\n");
699
700
701 let (ip, port, thread_count) = get_ip_port_thread_count();
702
703
704 let mut ip_readable = ip.to_string();
705
706 if ip.contains(":") {
707 ip_readable = [SYMBOL.opening_square_bracket, &ip, SYMBOL.closing_square_bracket].join("");
708 }
709
710 let bind_addr = [ip_readable, SYMBOL.colon.to_string(), port.to_string()].join(SYMBOL.empty_string);
711
712 #[cfg(feature = "http2")]
713 let protocol = {
714 let cert = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE).unwrap_or_default();
715 if cert.is_empty() { "http" } else { "https" }
716 };
717 #[cfg(not(feature = "http2"))]
718 let protocol = "http";
719
720 println!("Setting up {}://{}...", protocol, &bind_addr);
721
722 let boxed_listener = TcpListener::bind(&bind_addr);
723 if boxed_listener.is_err() {
724 let message = format!("unable to set up TCP listener: {}", boxed_listener.err().unwrap());
725 return Err(message);
726 }
727
728 let listener = boxed_listener.unwrap();
729 let pool = ThreadPool::new(thread_count as usize);
730
731
732 let server_url_thread_count = Log::server_url_thread_count(protocol, &bind_addr, thread_count);
733 println!("{}", server_url_thread_count);
734
735 Ok((listener, pool))
736 }
737
738 pub fn run(listener: TcpListener,
746 pool: ThreadPool,
747 app: impl Application + Send + 'static + Clone) {
748 #[cfg(feature = "http1")]
749 {
750 use std::sync::Arc;
751 use std::sync::atomic::{AtomicBool, Ordering};
752
753 let shutdown = Arc::new(AtomicBool::new(false));
754 let s = shutdown.clone();
755 if let Err(e) = ctrlc::set_handler(move || {
756 s.store(true, Ordering::SeqCst);
757 }) {
758 eprintln!("unable to install signal handler: {}", e);
759 }
760 crate::config_reload::install_sighup_handler();
761 if let Err(e) = listener.set_nonblocking(true) {
762 eprintln!("unable to set non-blocking listener: {}", e);
763 }
764
765 loop {
766 if shutdown.load(Ordering::SeqCst) {
767 break;
768 }
769 if crate::config_reload::RELOAD_REQUESTED
770 .compare_exchange(true, false, Ordering::SeqCst, Ordering::Relaxed)
771 .is_ok()
772 {
773 crate::config_reload::reload();
774 }
775 match listener.accept() {
776 Ok((stream, peer_addr)) => {
777 Server::dispatch_connection(stream, peer_addr, &pool, app.clone());
778 }
779 Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
780 std::thread::sleep(Duration::from_millis(10));
781 }
782 Err(e) => {
783 eprintln!("accept error: {}", e);
784 break;
785 }
786 }
787 }
788
789 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
790 println!("Shutting down — waiting for in-flight connections to finish");
791 pool.join();
792 println!("Server stopped");
793 }
794
795 #[cfg(not(feature = "http1"))]
796 {
797 for boxed_stream in listener.incoming() {
798 match boxed_stream {
799 Err(e) => {
800 eprintln!("unable to get TCP stream: {}", e);
801 return;
802 }
803 Ok(stream) => {
804 let peer_addr = match stream.peer_addr() {
805 Ok(a) => a,
806 Err(e) => {
807 eprintln!("unable to read peer addr: {}", e);
808 return;
809 }
810 };
811 Server::dispatch_connection(stream, peer_addr, &pool, app.clone());
812 }
813 }
814 }
815 }
816 }
817
818 fn dispatch_connection(
819 stream: std::net::TcpStream,
820 peer_addr: std::net::SocketAddr,
821 pool: &ThreadPool,
822 app: impl Application + Send + 'static + Clone,
823 ) {
824 print!("Connection established, ");
825 if let Ok(local) = stream.local_addr() {
826 print!("local addr: {}", local);
827 }
828 println!(", peer addr: {}", peer_addr);
829
830 let (server_ip, server_port, _thread_count) = get_ip_port_thread_count();
831 let connection = ConnectionInfo {
832 client: Address {
833 ip: peer_addr.ip().to_string(),
834 port: peer_addr.port() as i32,
835 },
836 server: Address {
837 ip: server_ip,
838 port: server_port,
839 },
840 request_size: get_request_allocation_size(),
841 sni_hostname: None,
842 tls: false,
843 };
844
845 if let Err(e) = stream.set_read_timeout(Some(Duration::from_secs(30))) {
846 eprintln!("failed to set read timeout: {}", e);
847 }
848
849 pool.execute(move || {
850 let mut stream = stream;
851 let mut connection = connection;
852 if proxy_protocol::enabled() {
853 match proxy_protocol::read_blocking(&mut stream) {
855 Ok(Some(source)) => {
856 connection.client = Address { ip: source.ip().to_string(), port: source.port() as i32 };
857 }
858 Ok(None) => {}
859 Err(e) => {
860 eprintln!("PROXY protocol header from {}: {}", peer_addr, e);
861 return;
862 }
863 }
864 }
865 crate::metrics::connection_open();
866 let result = Server::process_upgradable(stream, connection, app, |stream| {
867 let reader = stream.try_clone().ok()?;
868 let writer = stream.try_clone().ok()?;
869 let _ = reader.set_read_timeout(None);
871 Some((Box::new(reader) as Box<dyn Read + Send>, Box::new(writer) as Box<dyn Write + Send>))
872 });
873 crate::metrics::connection_close();
874 if let Err(msg) = result {
875 crate::metrics::record_error();
876 eprintln!("{}", msg);
877 }
878 });
879 }
880
881}
882
883#[derive(Clone)]
885pub struct ConnectionInfo {
886 pub client: Address,
888 pub server: Address,
890 pub request_size: i64,
892 pub sni_hostname: Option<String>,
895 pub tls: bool,
898}
899
900impl Default for ConnectionInfo {
901 fn default() -> Self {
904 let unknown = Address { ip: "0.0.0.0".to_string(), port: 0 };
905 ConnectionInfo { client: unknown.clone(), server: unknown, request_size: 0, sni_hostname: None, tls: false }
906 }
907}
908
909#[derive(Clone)]
911pub struct Address {
912 pub ip: String,
913 pub port: i32
914}
915
916impl ConnectionInfo {
917 pub fn new(client: Address, server: Address) -> Self {
920 ConnectionInfo { client, server, request_size: 0, sni_hostname: None, tls: false }
921 }
922
923 pub fn peer_addr(&self) -> Option<std::net::SocketAddr> {
926 self.client.to_socket_addr()
927 }
928}
929
930impl Address {
931 pub fn to_socket_addr(&self) -> Option<std::net::SocketAddr> {
934 let ip: std::net::IpAddr = self.ip.parse().ok()?;
935 let port = u16::try_from(self.port).ok()?;
936 Some(std::net::SocketAddr::new(ip, port))
937 }
938}
939
940#[cfg(feature = "http2")]
943pub(crate) async fn serve_tls_connection(
944 mut tcp_stream: tokio::net::TcpStream,
945 peer_addr: std::net::SocketAddr,
946 acceptor: tokio_rustls::TlsAcceptor,
947 app: impl Application + Send + 'static + Clone,
948) {
949 let _ = tcp_stream.set_nodelay(true);
950 let Some(peer_addr) = client_address(&mut tcp_stream, peer_addr).await else { return };
951 let timed_out = || std::io::Error::from(std::io::ErrorKind::TimedOut);
952 let handshake = async {
953 #[cfg(feature = "acme")]
954 if crate::acme::on_demand::enabled() {
955 let lazy = tokio_rustls::LazyConfigAcceptor::new(rustls::server::Acceptor::default(), tcp_stream);
959 let start = tokio::time::timeout(http1_async::TLS_HANDSHAKE_TIMEOUT, lazy).await.map_err(|_| timed_out())??;
960 let hello = start.client_hello();
961 let name = hello.server_name().filter(|_| !crate::acme::tls_alpn::is_challenge(&hello)).map(str::to_string);
962 if let Some(name) = name {
963 crate::acme::on_demand::ensure(&name).await;
964 }
965 let finish = start.into_stream(acceptor.config().clone());
966 return tokio::time::timeout(http1_async::TLS_HANDSHAKE_TIMEOUT, finish).await.map_err(|_| timed_out())?;
967 }
968 tokio::time::timeout(http1_async::TLS_HANDSHAKE_TIMEOUT, acceptor.accept(tcp_stream)).await.map_err(|_| timed_out())?
969 };
970 match handshake.await {
971 Err(e) if e.kind() == std::io::ErrorKind::TimedOut => {} Err(e) => {
973 crate::metrics::tls::record_handshake_failure();
974 eprintln!("TLS handshake failed: {}", e)
975 }
976 Ok(tls_stream) => {
977 let server_conn = tls_stream.get_ref().1;
978 crate::metrics::tls::record_rustls(server_conn);
979 let sni = server_conn.server_name().map(|s| s.to_string());
980 let protocol = server_conn.alpn_protocol().map(|p| p.to_vec());
981
982 match protocol.as_deref() {
983 #[cfg(feature = "acme")]
985 Some(crate::acme::tls_alpn::ALPN) => {}
986 Some(b"h2") => {
987 if let Err(e) = crate::h2_server::handle_connection(tls_stream, peer_addr, sni, app).await {
988 eprintln!("H2 connection error: {}", e);
989 }
990 }
991 _ => {
992 crate::metrics::connection_open();
993 let result = http1_async::serve(tls_stream, peer_addr, sni, true, app).await;
994 crate::metrics::connection_close();
995 if let Err(e) = result {
996 crate::metrics::record_error();
997 eprintln!("H1 TLS error: {}", e);
998 }
999 }
1000 }
1001 }
1002 }
1003}
1004
1005#[cfg(feature = "http2")]
1007pub(crate) async fn serve_plain_connection(
1008 tcp_stream: tokio::net::TcpStream,
1009 peer_addr: std::net::SocketAddr,
1010 app: impl Application + Send + 'static + Clone,
1011) {
1012 let mut tcp_stream = tcp_stream;
1015 let _ = tcp_stream.set_nodelay(true);
1016 let Some(peer_addr) = client_address(&mut tcp_stream, peer_addr).await else { return };
1017 if starts_with_h2_preface(&tcp_stream).await {
1018 if let Err(e) = crate::h2_server::serve(tcp_stream, peer_addr, None, false, app).await {
1019 eprintln!("H2C connection error: {}", e);
1020 }
1021 return;
1022 }
1023 crate::metrics::connection_open();
1024 let result = http1_async::serve(tcp_stream, peer_addr, None, false, app).await;
1025 crate::metrics::connection_close();
1026 if let Err(e) = result {
1027 crate::metrics::record_error();
1028 eprintln!("{}", e);
1029 }
1030}
1031
1032#[cfg(feature = "http2")]
1036async fn client_address(tcp_stream: &mut tokio::net::TcpStream, peer_addr: std::net::SocketAddr) -> Option<std::net::SocketAddr> {
1037 if !proxy_protocol::enabled() {
1038 return Some(peer_addr);
1039 }
1040 match tokio::time::timeout(http1_async::TLS_HANDSHAKE_TIMEOUT, proxy_protocol::read_async(tcp_stream)).await {
1041 Ok(Ok(source)) => Some(source.unwrap_or(peer_addr)),
1042 Ok(Err(e)) => {
1043 eprintln!("PROXY protocol header from {}: {}", peer_addr, e);
1044 None
1045 }
1046 Err(_) => None,
1047 }
1048}
1049
1050#[cfg(feature = "http2")]
1055async fn starts_with_h2_preface(tcp_stream: &tokio::net::TcpStream) -> bool {
1056 const PREFACE: &[u8; 24] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
1057 let mut seen = [0u8; 24];
1058 let deadline = tokio::time::Instant::now() + http1_async::READ_TIMEOUT;
1059 loop {
1060 let n = match tokio::time::timeout_at(deadline, tcp_stream.peek(&mut seen)).await {
1061 Ok(Ok(n)) => n,
1062 _ => return false,
1063 };
1064 if n == 0 || seen[..n] != PREFACE[..n] {
1065 return false;
1066 }
1067 if n == PREFACE.len() {
1068 return true;
1069 }
1070 tokio::time::sleep(std::time::Duration::from_millis(5)).await;
1072 }
1073}
1074
1075#[cfg(feature = "http2")]
1078async fn accept_backoff(e: std::io::Error) {
1079 eprintln!("TCP accept error: {}", e);
1080 tokio::time::sleep(std::time::Duration::from_millis(50)).await;
1081}
1082
1083#[cfg(feature = "http2")]
1085fn shutdown_requests() -> &'static tokio::sync::watch::Sender<bool> {
1086 static REQUESTS: std::sync::OnceLock<tokio::sync::watch::Sender<bool>> = std::sync::OnceLock::new();
1087 REQUESTS.get_or_init(|| tokio::sync::watch::channel(false).0)
1088}
1089
1090#[cfg(feature = "http2")]
1094pub fn request_shutdown() {
1095 shutdown_requests().send_replace(true);
1096}
1097
1098#[cfg(feature = "http2")]
1101async fn sigterm() {
1102 let requested = async {
1103 let mut requests = shutdown_requests().subscribe();
1104 let _ = requests.wait_for(|stop| *stop).await;
1105 };
1106 #[cfg(unix)]
1107 {
1108 if let Ok(mut s) = tokio::signal::unix::signal(
1109 tokio::signal::unix::SignalKind::terminate()
1110 ) {
1111 tokio::select! {
1112 _ = s.recv() => {}
1113 _ = requested => {}
1114 }
1115 } else {
1116 requested.await
1117 }
1118 }
1119 #[cfg(not(unix))]
1120 requested.await
1121}
1122
1123#[cfg(feature = "http2")]
1125async fn sighup() {
1126 #[cfg(unix)]
1127 {
1128 if let Ok(mut s) = tokio::signal::unix::signal(
1129 tokio::signal::unix::SignalKind::hangup()
1130 ) {
1131 s.recv().await;
1132 } else {
1133 std::future::pending::<()>().await
1134 }
1135 }
1136 #[cfg(not(unix))]
1137 std::future::pending::<()>().await
1138}
1139
1140#[cfg(feature = "http2")]
1147pub(crate) async fn bind_all_families(ip: &str, port: u16) -> Result<Vec<tokio::net::TcpListener>, String> {
1148 use tokio::net::TcpListener;
1149 if ip != "0.0.0.0" {
1150 let addr = if ip.contains(':') { format!("[{ip}]:{port}") } else { format!("{ip}:{port}") };
1151 return TcpListener::bind(&addr).await.map(|l| vec![l]).map_err(|e| format!("{addr}: {e}"));
1152 }
1153 let mut listeners = Vec::new();
1154 let mut errors = Vec::new();
1155 for addr in [format!("[::]:{port}"), format!("0.0.0.0:{port}")] {
1156 match TcpListener::bind(&addr).await {
1157 Ok(l) => listeners.push(l),
1158 Err(e) => errors.push(format!("{addr}: {e}")),
1159 }
1160 }
1161 if listeners.is_empty() {
1162 return Err(errors.join("; "));
1163 }
1164 Ok(listeners)
1165}
1166
1167#[cfg(feature = "http2")]
1168impl Server {
1169 pub async fn run_tls(
1170 listener: TcpListener,
1171 pool: ThreadPool,
1172 app: impl Application + Send + 'static + Clone,
1173 ) {
1174 use crate::tls::create_tls_acceptor_from_vhosts;
1175
1176 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1177 .unwrap_or_default();
1178 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
1179 .unwrap_or_default();
1180
1181 if cert_path.is_empty() || key_path.is_empty() {
1182 println!("No TLS certificate configured — serving plain HTTP/1.1.");
1183 drop(pool);
1184 Server::run_plain(listener, app).await;
1185 return;
1186 }
1187
1188 let vhosts = crate::entry_point::get_virtual_hosts();
1189 let mut tls_acceptor = match create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1190 Ok(a) => a,
1191 Err(e) => {
1192 eprintln!("TLS setup failed: {}", e);
1193 return;
1194 }
1195 };
1196 #[cfg(feature = "acme")]
1198 crate::acme::tls_alpn::note_tls_listener();
1199
1200 #[cfg(unix)]
1201 if per_core::enabled() {
1202 println!("Listening for TLS connections (HTTP/1.1 + HTTP/2), per-core runtimes...");
1203 let (acceptor_tx, acceptor_rx) = tokio::sync::watch::channel(tls_acceptor);
1204 let accept_loop = move |listener: tokio::net::TcpListener, mut stop: tokio::sync::watch::Receiver<bool>| {
1205 let app = app.clone();
1206 let acceptor_rx = acceptor_rx.clone();
1207 async move {
1208 loop {
1209 tokio::select! {
1210 result = listener.accept() => match result {
1211 Ok((tcp_stream, peer_addr)) => {
1212 let acceptor = acceptor_rx.borrow().clone();
1213 tokio::spawn(serve_tls_connection(tcp_stream, peer_addr, acceptor, app.clone()));
1214 }
1215 Err(e) => accept_backoff(e).await,
1216 },
1217 _ = per_core::stopped(&mut stop) => break,
1218 }
1219 }
1220 }
1221 };
1222 Server::run_per_core(listener, accept_loop, move || {
1223 let vhosts = crate::entry_point::get_virtual_hosts();
1224 if let Ok(new_acceptor) = create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1225 let _ = acceptor_tx.send(new_acceptor);
1226 println!("[TLS] Certificates reloaded ({} virtual hosts).", vhosts.len());
1227 }
1228 })
1229 .await;
1230 return;
1231 }
1232
1233 listener
1234 .set_nonblocking(true)
1235 .expect("failed to set TCP listener to non-blocking");
1236 let tokio_listener = tokio::net::TcpListener::from_std(listener)
1237 .expect("failed to convert TCP listener to tokio");
1238
1239 println!("Listening for TLS connections (HTTP/1.1 + HTTP/2)...");
1240
1241 loop {
1242 tokio::select! {
1243 result = tokio_listener.accept() => {
1244 match result {
1245 Ok((tcp_stream, peer_addr)) => {
1246 tokio::spawn(serve_tls_connection(tcp_stream, peer_addr, tls_acceptor.clone(), app.clone()));
1247 }
1248 Err(e) => eprintln!("TCP accept error: {}", e),
1249 }
1250 }
1251 _ = tokio::signal::ctrl_c() => {
1252 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1253 println!("\nShutting down gracefully (SIGINT).");
1254 break;
1255 }
1256 _ = sigterm() => {
1257 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1258 println!("\nShutting down gracefully (SIGTERM).");
1259 break;
1260 }
1261 _ = sighup() => {
1262 crate::config_reload::reload();
1263 let vhosts = crate::entry_point::get_virtual_hosts();
1264 if let Ok(new_acceptor) = create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1265 tls_acceptor = new_acceptor;
1266 println!("[TLS] Certificates reloaded ({} virtual hosts).", vhosts.len());
1267 }
1268 }
1269 }
1270 }
1271 }
1272
1273 pub async fn run_plain(listener: TcpListener, app: impl Application + Send + 'static + Clone) {
1279 #[cfg(unix)]
1280 if per_core::enabled() {
1281 let accept_loop = move |listener: tokio::net::TcpListener, mut stop: tokio::sync::watch::Receiver<bool>| {
1282 let app = app.clone();
1283 async move {
1284 loop {
1285 tokio::select! {
1286 result = listener.accept() => match result {
1287 Ok((tcp_stream, peer_addr)) => {
1288 tokio::spawn(serve_plain_connection(tcp_stream, peer_addr, app.clone()));
1289 }
1290 Err(e) => accept_backoff(e).await,
1291 },
1292 _ = per_core::stopped(&mut stop) => break,
1293 }
1294 }
1295 }
1296 };
1297 Server::run_per_core(listener, accept_loop, || {}).await;
1298 return;
1299 }
1300
1301 listener
1302 .set_nonblocking(true)
1303 .expect("failed to set TCP listener to non-blocking");
1304 let tokio_listener = tokio::net::TcpListener::from_std(listener)
1305 .expect("failed to convert TCP listener to tokio");
1306
1307 loop {
1308 tokio::select! {
1309 result = tokio_listener.accept() => {
1310 match result {
1311 Ok((tcp_stream, peer_addr)) => {
1312 tokio::spawn(serve_plain_connection(tcp_stream, peer_addr, app.clone()));
1313 }
1314 Err(e) => accept_backoff(e).await,
1315 }
1316 }
1317 _ = tokio::signal::ctrl_c() => {
1318 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1319 println!("\nShutting down gracefully (SIGINT).");
1320 break;
1321 }
1322 _ = sigterm() => {
1323 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1324 println!("\nShutting down gracefully (SIGTERM).");
1325 break;
1326 }
1327 _ = sighup() => {
1328 crate::config_reload::reload();
1329 }
1330 }
1331 }
1332 }
1333
1334 #[cfg(unix)]
1339 async fn run_per_core<F, Fut>(listener: TcpListener, accept_loop: F, on_reload: impl Fn())
1340 where
1341 F: Fn(tokio::net::TcpListener, tokio::sync::watch::Receiver<bool>) -> Fut + Send + Clone + 'static,
1342 Fut: std::future::Future<Output = ()>,
1343 {
1344 let addr = match listener.local_addr() {
1345 Ok(a) => a,
1346 Err(e) => return eprintln!("per-core runtimes: {}", e),
1347 };
1348 drop(listener);
1350 let count = per_core::runtime_count();
1351 let (stop_tx, stop_rx) = tokio::sync::watch::channel(false);
1352 let handles = per_core::spawn(addr, count, stop_rx, accept_loop);
1353 println!("Started {} per-core runtimes on {}.", handles.len(), addr);
1354
1355 loop {
1356 tokio::select! {
1357 _ = tokio::signal::ctrl_c() => {
1358 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1359 println!("\nShutting down gracefully (SIGINT).");
1360 break;
1361 }
1362 _ = sigterm() => {
1363 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1364 println!("\nShutting down gracefully (SIGTERM).");
1365 break;
1366 }
1367 _ = sighup() => {
1368 crate::config_reload::reload();
1369 on_reload();
1370 }
1371 }
1372 }
1373 let _ = stop_tx.send(true);
1374 let _ = tokio::task::spawn_blocking(move || {
1375 for h in handles {
1376 let _ = h.join();
1377 }
1378 })
1379 .await;
1380 }
1381
1382 pub async fn run_redirect() {
1386 use std::env;
1387
1388 let cert_path = env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1389 .unwrap_or_default();
1390 if cert_path.is_empty() {
1391 return;
1392 }
1393
1394 let redirect_port_str = env::var(crate::entry_point::Config::RWS_CONFIG_HTTP_REDIRECT_PORT)
1395 .unwrap_or_default();
1396 if redirect_port_str.is_empty() {
1397 return;
1398 }
1399
1400 let redirect_port: u16 = match redirect_port_str.parse() {
1401 Ok(p) => p,
1402 Err(_) => {
1403 eprintln!("Invalid RWS_CONFIG_HTTP_REDIRECT_PORT: {}", redirect_port_str);
1404 return;
1405 }
1406 };
1407
1408 let (server_ip, server_port, _) = get_ip_port_thread_count();
1409 let listeners = match bind_all_families(&server_ip, redirect_port).await {
1410 Ok(l) => l,
1411 Err(e) => {
1412 eprintln!("HTTP redirect listener error on port {}: {}", redirect_port, e);
1413 return;
1414 }
1415 };
1416
1417 println!("HTTP→HTTPS redirect listening on http://{}:{}", server_ip, redirect_port);
1418 #[cfg(feature = "acme")]
1419 crate::acme::note_redirect_listener(redirect_port);
1420
1421 for listener in listeners {
1422 tokio::spawn(async move {
1423 loop {
1424 match listener.accept().await {
1425 Ok((stream, _peer)) => {
1426 tokio::spawn(Server::handle_redirect_connection(stream, server_port));
1427 }
1428 Err(e) => eprintln!("HTTP redirect accept error: {}", e),
1429 }
1430 }
1431 });
1432 }
1433
1434 loop {
1435 tokio::select! {
1436 _ = tokio::signal::ctrl_c() => {
1437 println!("\nShutting down HTTP redirect listener (SIGINT).");
1438 break;
1439 }
1440 _ = sigterm() => {
1441 println!("\nShutting down HTTP redirect listener (SIGTERM).");
1442 break;
1443 }
1444 _ = sighup() => {
1445 crate::config_reload::reload();
1446 }
1447 }
1448 }
1449 }
1450
1451 pub(crate) async fn handle_redirect_connection(mut stream: tokio::net::TcpStream, https_port: i32) {
1454 use tokio::io::{AsyncReadExt, AsyncWriteExt};
1455 let mut buf = vec![0u8; 4096];
1456 let n = match stream.read(&mut buf).await {
1457 Ok(n) => n,
1458 Err(_) => return,
1459 };
1460 let text = String::from_utf8_lossy(&buf[..n]);
1461
1462 let uri = text.lines()
1463 .next()
1464 .and_then(|line| line.split_whitespace().nth(1))
1465 .unwrap_or("/")
1466 .to_string();
1467
1468 #[cfg(feature = "acme")]
1471 if let Some(challenge) = crate::acme::challenge_http_response_shared(&uri).await {
1472 let _ = stream.write_all(challenge.as_bytes()).await;
1473 return;
1474 }
1475
1476 let host_header = text.lines()
1477 .find(|l| l.to_lowercase().starts_with("host:"))
1478 .map(|l| l[5..].trim().to_string());
1479
1480 let location = match host_header {
1481 Some(h) => {
1482 let h_no_port = if h.starts_with('[') {
1484 h.find(']')
1486 .map(|i| h[..=i].to_string())
1487 .unwrap_or(h.clone())
1488 } else {
1489 h.rfind(':')
1490 .map(|i| h[..i].to_string())
1491 .unwrap_or(h.clone())
1492 };
1493 if https_port == 443 {
1494 format!("https://{}{}", h_no_port, uri)
1495 } else {
1496 format!("https://{}:{}{}", h_no_port, https_port, uri)
1497 }
1498 }
1499 None => format!("https://localhost:{}{}", https_port, uri),
1500 };
1501
1502 let response = format!(
1503 "HTTP/1.1 301 Moved Permanently\r\nLocation: {}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n",
1504 location
1505 );
1506 let _ = stream.write_all(response.as_bytes()).await;
1507 }
1508
1509}
1510
1511#[cfg(feature = "http3")]
1512impl Server {
1513 pub async fn run_quic(
1514 app: impl Application + Send + 'static + Clone,
1515 ) {
1516 use crate::tls::create_quinn_server_config_from_vhosts;
1517 use crate::h3_handler;
1518
1519 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1520 .unwrap_or_default();
1521 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
1522 .unwrap_or_default();
1523
1524 if cert_path.is_empty() || key_path.is_empty() {
1525 return;
1526 }
1527
1528 let vhosts = crate::entry_point::get_virtual_hosts();
1529 let server_config = match create_quinn_server_config_from_vhosts(&vhosts, &cert_path, &key_path) {
1530 Ok(c) => c,
1531 Err(e) => {
1532 eprintln!("QUIC TLS setup failed: {}", e);
1533 return;
1534 }
1535 };
1536
1537 let (server_ip, server_port, _) = get_ip_port_thread_count();
1538 let bind_addr = format!("{}:{}", server_ip, server_port);
1539 let addr: std::net::SocketAddr = match bind_addr.parse() {
1540 Ok(a) => a,
1541 Err(e) => {
1542 eprintln!("Invalid QUIC bind address '{}': {}", bind_addr, e);
1543 return;
1544 }
1545 };
1546
1547 let endpoint = match quinn::Endpoint::server(server_config, addr) {
1548 Ok(e) => e,
1549 Err(e) => {
1550 eprintln!("QUIC endpoint error: {}", e);
1551 return;
1552 }
1553 };
1554
1555 println!("Listening for QUIC/HTTP3 on UDP {}:{}", server_ip, server_port);
1556
1557 loop {
1558 tokio::select! {
1559 maybe = endpoint.accept() => {
1560 match maybe {
1561 Some(incoming) => {
1562 let app = app.clone();
1563 tokio::spawn(async move {
1564 match incoming.await {
1565 Ok(conn) => {
1566 let peer_addr = conn.remote_address();
1567 if let Err(e) = h3_handler::handle_connection(conn, peer_addr, app).await {
1568 eprintln!("H3 connection error: {}", e);
1569 }
1570 }
1571 Err(e) => eprintln!("QUIC connection error: {}", e),
1572 }
1573 });
1574 }
1575 None => break,
1576 }
1577 }
1578 _ = tokio::signal::ctrl_c() => {
1579 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1580 println!("\nShutting down QUIC (SIGINT).");
1581 endpoint.close(0u32.into(), b"shutdown");
1582 break;
1583 }
1584 _ = sigterm() => {
1585 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1586 println!("\nShutting down QUIC (SIGTERM).");
1587 endpoint.close(0u32.into(), b"shutdown");
1588 break;
1589 }
1590 _ = sighup() => {
1591 crate::config_reload::reload();
1592 }
1593 }
1594 }
1595 }
1596}
1597
1598