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