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