ferron/
request_handler.rs

1use std::convert::Infallible;
2use std::net::{IpAddr, SocketAddr};
3use std::str::FromStr;
4use std::sync::Arc;
5use std::time::Duration;
6
7use crate::ferron_res::server_software::SERVER_SOFTWARE;
8use crate::ferron_util::combine_config::combine_config;
9use crate::ferron_util::error_config::combine_error_config;
10use crate::ferron_util::error_pages::generate_default_error_page;
11use crate::ferron_util::url_sanitizer::sanitize_url;
12
13use crate::ferron_common::{
14  ErrorLogger, LogMessage, RequestData, ServerModuleHandlers, SocketData,
15};
16use async_channel::Sender;
17use chrono::prelude::*;
18use futures_util::TryStreamExt;
19use http::header::CONTENT_TYPE;
20use http_body_util::combinators::BoxBody;
21use http_body_util::{BodyExt, Empty, Full, StreamBody};
22use hyper::body::{Body, Bytes, Frame};
23use hyper::header::{self, HeaderName, HeaderValue};
24use hyper::{HeaderMap, Method, Request, Response, StatusCode};
25use hyper_tungstenite::is_upgrade_request;
26use tokio::fs;
27use tokio::io::BufReader;
28use tokio::time::timeout;
29use tokio_rustls_acme2::ResolvesServerCertAcme;
30use tokio_util::io::ReaderStream;
31use yaml_rust2::Yaml;
32
33async fn generate_error_response(
34  status_code: StatusCode,
35  config: &Yaml,
36  headers: &Option<HeaderMap>,
37) -> Response<BoxBody<Bytes, std::io::Error>> {
38  let bare_body =
39    generate_default_error_page(status_code, config["serverAdministratorEmail"].as_str());
40  let mut content_length: Option<u64> = bare_body.len().try_into().ok();
41  let mut response_body = Full::new(Bytes::from(bare_body))
42    .map_err(|e| match e {})
43    .boxed();
44
45  if let Some(error_pages) = config["errorPages"].as_vec() {
46    for error_page_yaml in error_pages {
47      if let Some(page_status_code) = error_page_yaml["scode"].as_i64() {
48        let page_status_code = match StatusCode::from_u16(match page_status_code.try_into() {
49          Ok(status_code) => status_code,
50          Err(_) => continue,
51        }) {
52          Ok(status_code) => status_code,
53          Err(_) => continue,
54        };
55        if status_code != page_status_code {
56          continue;
57        }
58        if let Some(page_path) = error_page_yaml["path"].as_str() {
59          let file = fs::File::open(page_path).await;
60
61          let file = match file {
62            Ok(file) => file,
63            Err(_) => continue,
64          };
65
66          content_length = match file.metadata().await {
67            Ok(metadata) => Some(metadata.len()),
68            Err(_) => None,
69          };
70
71          // Use BufReader for better performance.
72          let reader_stream = ReaderStream::new(BufReader::with_capacity(12800, file));
73
74          let stream_body = StreamBody::new(reader_stream.map_ok(Frame::data));
75          let boxed_body = stream_body.boxed();
76
77          response_body = boxed_body;
78
79          break;
80        }
81      }
82    }
83  }
84
85  let mut response_builder = Response::builder().status(status_code);
86
87  if let Some(headers) = headers {
88    let headers_iter = headers.iter();
89    for (name, value) in headers_iter {
90      if name != header::CONTENT_TYPE && name != header::CONTENT_LENGTH {
91        response_builder = response_builder.header(name, value);
92      }
93    }
94  }
95
96  if let Some(content_length) = content_length {
97    response_builder = response_builder.header(header::CONTENT_LENGTH, content_length);
98  }
99  response_builder =
100    response_builder.header(header::CONTENT_TYPE, HeaderValue::from_static("text/html"));
101
102  response_builder.body(response_body).unwrap_or_default()
103}
104
105#[allow(clippy::too_many_arguments)]
106async fn log_combined(
107  logger: &Sender<LogMessage>,
108  client_ip: IpAddr,
109  auth_user: Option<String>,
110  method: String,
111  request_path: String,
112  protocol: String,
113  status_code: u16,
114  content_length: Option<u64>,
115  referrer: Option<String>,
116  user_agent: Option<String>,
117) {
118  let now: DateTime<Local> = Local::now();
119  let formatted_time = now.format("%d/%b/%Y:%H:%M:%S %z").to_string();
120  logger
121    .send(LogMessage::new(
122      format!(
123        "{} - {} [{}] \"{} {} {}\" {} {} {} {}",
124        client_ip,
125        match auth_user {
126          Some(auth_user) => auth_user,
127          None => String::from("-"),
128        },
129        formatted_time,
130        method,
131        request_path,
132        protocol,
133        status_code,
134        match content_length {
135          Some(content_length) => format!("{content_length}"),
136          None => String::from("-"),
137        },
138        match referrer {
139          Some(referrer) => format!(
140            "\"{}\"",
141            referrer.replace("\\", "\\\\").replace("\"", "\\\"")
142          ),
143          None => String::from("-"),
144        },
145        match user_agent {
146          Some(user_agent) => format!(
147            "\"{}\"",
148            user_agent.replace("\\", "\\\\").replace("\"", "\\\"")
149          ),
150          None => String::from("-"),
151        },
152      ),
153      false,
154    ))
155    .await
156    .unwrap_or_default();
157}
158
159#[allow(clippy::too_many_arguments)]
160async fn request_handler_wrapped(
161  mut request: Request<BoxBody<Bytes, std::io::Error>>,
162  remote_address: SocketAddr,
163  local_address: SocketAddr,
164  encrypted: bool,
165  config: Arc<Yaml>,
166  logger: Sender<LogMessage>,
167  handlers_vec: Vec<Box<dyn ServerModuleHandlers + Send>>,
168  acme_http01_resolver_option: Option<Arc<ResolvesServerCertAcme>>,
169  http3_alt_port: Option<u16>,
170) -> Result<Response<BoxBody<Bytes, std::io::Error>>, Infallible> {
171  let is_proxy_request = match request.version() {
172    hyper::Version::HTTP_2 | hyper::Version::HTTP_3 => {
173      request.method() == hyper::Method::CONNECT && request.uri().host().is_some()
174    }
175    _ => request.uri().host().is_some(),
176  };
177  let is_connect_proxy_request = request.method() == hyper::Method::CONNECT;
178
179  // Collect request data for logging
180  let log_method = String::from(request.method().as_str());
181  let log_request_path = match is_proxy_request {
182    true => request.uri().to_string(),
183    false => format!(
184      "{}{}",
185      request.uri().path(),
186      match request.uri().query() {
187        Some(query) => format!("?{query}"),
188        None => String::from(""),
189      }
190    ),
191  };
192  let log_protocol = String::from(match request.version() {
193    hyper::Version::HTTP_09 => "HTTP/0.9",
194    hyper::Version::HTTP_10 => "HTTP/1.0",
195    hyper::Version::HTTP_11 => "HTTP/1.1",
196    hyper::Version::HTTP_2 => "HTTP/2.0",
197    hyper::Version::HTTP_3 => "HTTP/3.0",
198    _ => "HTTP/Unknown",
199  });
200  let log_referrer = match request.headers().get(header::REFERER) {
201    Some(header_value) => match header_value.to_str() {
202      Ok(header_value) => Some(String::from(header_value)),
203      Err(_) => None,
204    },
205    None => None,
206  };
207  let log_user_agent = match request.headers().get(header::USER_AGENT) {
208    Some(header_value) => match header_value.to_str() {
209      Ok(header_value) => Some(String::from(header_value)),
210      Err(_) => None,
211    },
212    None => None,
213  };
214  let log_enabled = config["global"]["logFilePath"].as_str().is_some();
215  let error_log_enabled = config["global"]["errorLogFilePath"].as_str().is_some();
216
217  // Construct SocketData
218  let mut socket_data = SocketData::new(remote_address, local_address, encrypted);
219
220  match request.version() {
221    hyper::Version::HTTP_2 | hyper::Version::HTTP_3 => {
222      // Set "Host" request header for HTTP/2 and HTTP/3 connections
223      if let Some(authority) = request.uri().authority() {
224        let authority = authority.to_owned();
225        let headers = request.headers_mut();
226        if !headers.contains_key(header::HOST) {
227          if let Ok(authority_value) = HeaderValue::from_bytes(authority.as_str().as_bytes()) {
228            headers.append(header::HOST, authority_value);
229          }
230        }
231      }
232
233      // Normalize the Cookie header for HTTP/2 and HTTP/3
234      let mut cookie_normalized = String::new();
235      let mut cookie_set = false;
236      let headers = request.headers_mut();
237      for cookie in headers.get_all(header::COOKIE) {
238        if let Ok(cookie) = cookie.to_str() {
239          if cookie_set {
240            cookie_normalized.push_str("; ");
241          }
242          cookie_set = true;
243          cookie_normalized.push_str(cookie);
244        }
245      }
246      if cookie_set {
247        if let Ok(cookie_value) = HeaderValue::from_bytes(cookie_normalized.as_bytes()) {
248          headers.insert(header::COOKIE, cookie_value);
249        }
250      }
251    }
252    _ => (),
253  }
254
255  let host_header_option = request.headers().get(header::HOST);
256  if let Some(header_data) = host_header_option {
257    match header_data.to_str() {
258      Ok(host_header) => {
259        let host_header_lower_case = host_header.to_lowercase();
260        if host_header_lower_case != *host_header {
261          let host_header_value = match HeaderValue::from_str(&host_header_lower_case) {
262            Ok(host_header_value) => host_header_value,
263            Err(err) => {
264              if error_log_enabled {
265                logger
266                  .send(LogMessage::new(
267                    format!("Host header sanitation error: {err}"),
268                    true,
269                  ))
270                  .await
271                  .unwrap_or_default();
272              }
273              let response = Response::builder()
274                .status(StatusCode::BAD_REQUEST)
275                .header(header::CONTENT_TYPE, HeaderValue::from_static("text/html"))
276                .body(
277                  Full::new(Bytes::from(generate_default_error_page(
278                    StatusCode::BAD_REQUEST,
279                    None,
280                  )))
281                  .map_err(|e| match e {})
282                  .boxed(),
283                )
284                .unwrap_or_default();
285
286              if log_enabled {
287                log_combined(
288                  &logger,
289                  socket_data.remote_addr.ip(),
290                  None,
291                  log_method,
292                  log_request_path,
293                  log_protocol,
294                  response.status().as_u16(),
295                  match response.headers().get(header::CONTENT_LENGTH) {
296                    Some(header_value) => match header_value.to_str() {
297                      Ok(header_value) => match header_value.parse::<u64>() {
298                        Ok(content_length) => Some(content_length),
299                        Err(_) => response.body().size_hint().exact(),
300                      },
301                      Err(_) => response.body().size_hint().exact(),
302                    },
303                    None => response.body().size_hint().exact(),
304                  },
305                  log_referrer,
306                  log_user_agent,
307                )
308                .await;
309              }
310              let (mut response_parts, response_body) = response.into_parts();
311              if let Some(http3_alt_port) = http3_alt_port {
312                if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
313                  Some(value) => {
314                    let header_value_old = String::from_utf8_lossy(value.as_bytes());
315                    let header_value_new =
316                      format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
317
318                    if header_value_old != header_value_new {
319                      HeaderValue::from_bytes(
320                        format!("{header_value_old}, {header_value_new}").as_bytes(),
321                      )
322                    } else {
323                      HeaderValue::from_bytes(header_value_old.as_bytes())
324                    }
325                  }
326                  None => HeaderValue::from_bytes(
327                    format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
328                  ),
329                } {
330                  response_parts.headers.insert(header::ALT_SVC, header_value);
331                }
332              }
333              response_parts
334                .headers
335                .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
336
337              return Ok(Response::from_parts(response_parts, response_body));
338            }
339          };
340
341          request
342            .headers_mut()
343            .insert(header::HOST, host_header_value);
344        }
345      }
346      Err(err) => {
347        if error_log_enabled {
348          logger
349            .send(LogMessage::new(
350              format!("Host header sanitation error: {err}"),
351              true,
352            ))
353            .await
354            .unwrap_or_default();
355        }
356        let response = Response::builder()
357          .status(StatusCode::BAD_REQUEST)
358          .header(header::CONTENT_TYPE, HeaderValue::from_static("text/html"))
359          .body(
360            Full::new(Bytes::from(generate_default_error_page(
361              StatusCode::BAD_REQUEST,
362              None,
363            )))
364            .map_err(|e| match e {})
365            .boxed(),
366          )
367          .unwrap_or_default();
368        if log_enabled {
369          log_combined(
370            &logger,
371            socket_data.remote_addr.ip(),
372            None,
373            log_method,
374            log_request_path,
375            log_protocol,
376            response.status().as_u16(),
377            match response.headers().get(header::CONTENT_LENGTH) {
378              Some(header_value) => match header_value.to_str() {
379                Ok(header_value) => match header_value.parse::<u64>() {
380                  Ok(content_length) => Some(content_length),
381                  Err(_) => response.body().size_hint().exact(),
382                },
383                Err(_) => response.body().size_hint().exact(),
384              },
385              None => response.body().size_hint().exact(),
386            },
387            log_referrer,
388            log_user_agent,
389          )
390          .await;
391        }
392        let (mut response_parts, response_body) = response.into_parts();
393        if let Some(http3_alt_port) = http3_alt_port {
394          if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
395            Some(value) => {
396              let header_value_old = String::from_utf8_lossy(value.as_bytes());
397              let header_value_new =
398                format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
399
400              if header_value_old != header_value_new {
401                HeaderValue::from_bytes(
402                  format!("{header_value_old}, {header_value_new}").as_bytes(),
403                )
404              } else {
405                HeaderValue::from_bytes(header_value_old.as_bytes())
406              }
407            }
408            None => HeaderValue::from_bytes(
409              format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
410            ),
411          } {
412            response_parts.headers.insert(header::ALT_SVC, header_value);
413          }
414        }
415        response_parts
416          .headers
417          .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
418
419        return Ok(Response::from_parts(response_parts, response_body));
420      }
421    }
422  };
423
424  // Combine the server configuration
425  let mut combined_config = match combine_config(
426    config.clone(),
427    match is_proxy_request || is_connect_proxy_request {
428      false => match request.headers().get(header::HOST) {
429        Some(value) => value.to_str().ok(),
430        None => None,
431      },
432      true => None,
433    },
434    local_address.ip(),
435    request.uri().path(),
436  ) {
437    Some(config) => config,
438    None => {
439      if error_log_enabled {
440        logger
441          .send(LogMessage::new(
442            String::from("Cannot determine server configuration"),
443            true,
444          ))
445          .await
446          .unwrap_or_default();
447      }
448      let response = Response::builder()
449        .status(StatusCode::INTERNAL_SERVER_ERROR)
450        .header(header::CONTENT_TYPE, HeaderValue::from_static("text/html"))
451        .body(
452          Full::new(Bytes::from(generate_default_error_page(
453            StatusCode::INTERNAL_SERVER_ERROR,
454            None,
455          )))
456          .map_err(|e| match e {})
457          .boxed(),
458        )
459        .unwrap_or_default();
460      if log_enabled {
461        log_combined(
462          &logger,
463          socket_data.remote_addr.ip(),
464          None,
465          log_method,
466          log_request_path,
467          log_protocol,
468          response.status().as_u16(),
469          match response.headers().get(header::CONTENT_LENGTH) {
470            Some(header_value) => match header_value.to_str() {
471              Ok(header_value) => match header_value.parse::<u64>() {
472                Ok(content_length) => Some(content_length),
473                Err(_) => response.body().size_hint().exact(),
474              },
475              Err(_) => response.body().size_hint().exact(),
476            },
477            None => response.body().size_hint().exact(),
478          },
479          log_referrer,
480          log_user_agent,
481        )
482        .await;
483      }
484      let (mut response_parts, response_body) = response.into_parts();
485      if let Some(http3_alt_port) = http3_alt_port {
486        if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
487          Some(value) => {
488            let header_value_old = String::from_utf8_lossy(value.as_bytes());
489            let header_value_new = format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
490
491            if header_value_old != header_value_new {
492              HeaderValue::from_bytes(format!("{header_value_old}, {header_value_new}").as_bytes())
493            } else {
494              HeaderValue::from_bytes(header_value_old.as_bytes())
495            }
496          }
497          None => HeaderValue::from_bytes(
498            format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
499          ),
500        } {
501          response_parts.headers.insert(header::ALT_SVC, header_value);
502        }
503      }
504      response_parts
505        .headers
506        .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
507
508      return Ok(Response::from_parts(response_parts, response_body));
509    }
510  };
511
512  let url_pathname = request.uri().path();
513  let sanitized_url_pathname = match sanitize_url(
514    url_pathname,
515    combined_config["allowDoubleSlashes"]
516      .as_bool()
517      .unwrap_or_default(),
518  ) {
519    Ok(sanitized_url) => sanitized_url,
520    Err(err) => {
521      if error_log_enabled {
522        logger
523          .send(LogMessage::new(
524            format!("URL sanitation error: {err}"),
525            true,
526          ))
527          .await
528          .unwrap_or_default();
529      }
530      let response =
531        generate_error_response(StatusCode::BAD_REQUEST, &combined_config, &None).await;
532      if log_enabled {
533        log_combined(
534          &logger,
535          socket_data.remote_addr.ip(),
536          None,
537          log_method,
538          log_request_path,
539          log_protocol,
540          response.status().as_u16(),
541          match response.headers().get(header::CONTENT_LENGTH) {
542            Some(header_value) => match header_value.to_str() {
543              Ok(header_value) => match header_value.parse::<u64>() {
544                Ok(content_length) => Some(content_length),
545                Err(_) => response.body().size_hint().exact(),
546              },
547              Err(_) => response.body().size_hint().exact(),
548            },
549            None => response.body().size_hint().exact(),
550          },
551          log_referrer,
552          log_user_agent,
553        )
554        .await;
555      }
556      let (mut response_parts, response_body) = response.into_parts();
557      if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
558        let custom_headers_hash_iter = custom_headers_hash.iter();
559        for (header_name, header_value) in custom_headers_hash_iter {
560          if let Some(header_name) = header_name.as_str() {
561            if let Some(header_value) = header_value.as_str() {
562              if !response_parts.headers.contains_key(header_name) {
563                if let Ok(header_value) =
564                  HeaderValue::from_str(&header_value.replace("{path}", url_pathname))
565                {
566                  if let Ok(header_name) = HeaderName::from_str(header_name) {
567                    response_parts.headers.insert(header_name, header_value);
568                  }
569                }
570              }
571            }
572          }
573        }
574      }
575      if let Some(http3_alt_port) = http3_alt_port {
576        if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
577          Some(value) => {
578            let header_value_old = String::from_utf8_lossy(value.as_bytes());
579            let header_value_new = format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
580
581            if header_value_old != header_value_new {
582              HeaderValue::from_bytes(format!("{header_value_old}, {header_value_new}").as_bytes())
583            } else {
584              HeaderValue::from_bytes(header_value_old.as_bytes())
585            }
586          }
587          None => HeaderValue::from_bytes(
588            format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
589          ),
590        } {
591          response_parts.headers.insert(header::ALT_SVC, header_value);
592        }
593      }
594      response_parts
595        .headers
596        .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
597
598      return Ok(Response::from_parts(response_parts, response_body));
599    }
600  };
601
602  if sanitized_url_pathname != url_pathname {
603    let (mut parts, body) = request.into_parts();
604    let mut url_parts = parts.uri.into_parts();
605    url_parts.path_and_query = Some(
606      match format!(
607        "{}{}",
608        sanitized_url_pathname,
609        match url_parts.path_and_query {
610          Some(path_and_query) => {
611            match path_and_query.query() {
612              Some(query) => format!("?{query}"),
613              None => String::from(""),
614            }
615          }
616          None => String::from(""),
617        }
618      )
619      .parse()
620      {
621        Ok(path_and_query) => path_and_query,
622        Err(err) => {
623          if error_log_enabled {
624            logger
625              .send(LogMessage::new(
626                format!("URL sanitation error: {err}"),
627                true,
628              ))
629              .await
630              .unwrap_or_default();
631          }
632          let response =
633            generate_error_response(StatusCode::BAD_REQUEST, &combined_config, &None).await;
634          if log_enabled {
635            log_combined(
636              &logger,
637              socket_data.remote_addr.ip(),
638              None,
639              log_method,
640              log_request_path,
641              log_protocol,
642              response.status().as_u16(),
643              match response.headers().get(header::CONTENT_LENGTH) {
644                Some(header_value) => match header_value.to_str() {
645                  Ok(header_value) => match header_value.parse::<u64>() {
646                    Ok(content_length) => Some(content_length),
647                    Err(_) => response.body().size_hint().exact(),
648                  },
649                  Err(_) => response.body().size_hint().exact(),
650                },
651                None => response.body().size_hint().exact(),
652              },
653              log_referrer,
654              log_user_agent,
655            )
656            .await;
657          }
658          let (mut response_parts, response_body) = response.into_parts();
659          if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
660            let custom_headers_hash_iter = custom_headers_hash.iter();
661            for (header_name, header_value) in custom_headers_hash_iter {
662              if let Some(header_name) = header_name.as_str() {
663                if let Some(header_value) = header_value.as_str() {
664                  if !response_parts.headers.contains_key(header_name) {
665                    if let Ok(header_value) = HeaderValue::from_str(
666                      &header_value.replace("{path}", &sanitized_url_pathname),
667                    ) {
668                      if let Ok(header_name) = HeaderName::from_str(header_name) {
669                        response_parts.headers.insert(header_name, header_value);
670                      }
671                    }
672                  }
673                }
674              }
675            }
676          }
677          if let Some(http3_alt_port) = http3_alt_port {
678            if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
679              Some(value) => {
680                let header_value_old = String::from_utf8_lossy(value.as_bytes());
681                let header_value_new =
682                  format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
683
684                if header_value_old != header_value_new {
685                  HeaderValue::from_bytes(
686                    format!("{header_value_old}, {header_value_new}").as_bytes(),
687                  )
688                } else {
689                  HeaderValue::from_bytes(header_value_old.as_bytes())
690                }
691              }
692              None => HeaderValue::from_bytes(
693                format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
694              ),
695            } {
696              response_parts.headers.insert(header::ALT_SVC, header_value);
697            }
698          }
699          response_parts
700            .headers
701            .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
702
703          return Ok(Response::from_parts(response_parts, response_body));
704        }
705      },
706    );
707    parts.uri = match hyper::Uri::from_parts(url_parts) {
708      Ok(uri) => uri,
709      Err(err) => {
710        if error_log_enabled {
711          logger
712            .send(LogMessage::new(
713              format!("URL sanitation error: {err}"),
714              true,
715            ))
716            .await
717            .unwrap_or_default();
718        }
719        let response =
720          generate_error_response(StatusCode::BAD_REQUEST, &combined_config, &None).await;
721        if log_enabled {
722          log_combined(
723            &logger,
724            socket_data.remote_addr.ip(),
725            None,
726            log_method,
727            log_request_path,
728            log_protocol,
729            response.status().as_u16(),
730            match response.headers().get(header::CONTENT_LENGTH) {
731              Some(header_value) => match header_value.to_str() {
732                Ok(header_value) => match header_value.parse::<u64>() {
733                  Ok(content_length) => Some(content_length),
734                  Err(_) => response.body().size_hint().exact(),
735                },
736                Err(_) => response.body().size_hint().exact(),
737              },
738              None => response.body().size_hint().exact(),
739            },
740            log_referrer,
741            log_user_agent,
742          )
743          .await;
744        }
745        let (mut response_parts, response_body) = response.into_parts();
746        if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
747          let custom_headers_hash_iter = custom_headers_hash.iter();
748          for (header_name, header_value) in custom_headers_hash_iter {
749            if let Some(header_name) = header_name.as_str() {
750              if let Some(header_value) = header_value.as_str() {
751                if !response_parts.headers.contains_key(header_name) {
752                  if let Ok(header_value) =
753                    HeaderValue::from_str(&header_value.replace("{path}", &sanitized_url_pathname))
754                  {
755                    if let Ok(header_name) = HeaderName::from_str(header_name) {
756                      response_parts.headers.insert(header_name, header_value);
757                    }
758                  }
759                }
760              }
761            }
762          }
763        }
764        if let Some(http3_alt_port) = http3_alt_port {
765          if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
766            Some(value) => {
767              let header_value_old = String::from_utf8_lossy(value.as_bytes());
768              let header_value_new =
769                format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
770
771              if header_value_old != header_value_new {
772                HeaderValue::from_bytes(
773                  format!("{header_value_old}, {header_value_new}").as_bytes(),
774                )
775              } else {
776                HeaderValue::from_bytes(header_value_old.as_bytes())
777              }
778            }
779            None => HeaderValue::from_bytes(
780              format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
781            ),
782          } {
783            response_parts.headers.insert(header::ALT_SVC, header_value);
784          }
785        }
786        response_parts
787          .headers
788          .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
789
790        return Ok(Response::from_parts(response_parts, response_body));
791      }
792    };
793    request = Request::from_parts(parts, body);
794    if let Some(new_combined_config) = combine_config(
795      config.clone(),
796      match is_proxy_request || is_connect_proxy_request {
797        false => match request.headers().get(header::HOST) {
798          Some(value) => value.to_str().ok(),
799          None => None,
800        },
801        true => None,
802      },
803      local_address.ip(),
804      request.uri().path(),
805    ) {
806      combined_config = new_combined_config;
807    }
808  }
809  drop(config);
810
811  if request.uri().path() == "*" {
812    let response = match request.method() {
813      &Method::OPTIONS => Response::builder()
814        .status(StatusCode::NO_CONTENT)
815        .header(
816          header::ALLOW,
817          HeaderValue::from_static("GET, POST, HEAD, OPTIONS"),
818        )
819        .body(Empty::new().map_err(|e| match e {}).boxed())
820        .unwrap_or_default(),
821      _ => {
822        let mut header_map = HeaderMap::new();
823        header_map.insert(
824          header::ALLOW,
825          HeaderValue::from_static("GET, POST, HEAD, OPTIONS"),
826        );
827        generate_error_response(StatusCode::BAD_REQUEST, &combined_config, &Some(header_map)).await
828      }
829    };
830    if log_enabled {
831      log_combined(
832        &logger,
833        socket_data.remote_addr.ip(),
834        None,
835        log_method,
836        log_request_path,
837        log_protocol,
838        response.status().as_u16(),
839        match response.headers().get(header::CONTENT_LENGTH) {
840          Some(header_value) => match header_value.to_str() {
841            Ok(header_value) => match header_value.parse::<u64>() {
842              Ok(content_length) => Some(content_length),
843              Err(_) => response.body().size_hint().exact(),
844            },
845            Err(_) => response.body().size_hint().exact(),
846          },
847          None => response.body().size_hint().exact(),
848        },
849        log_referrer,
850        log_user_agent,
851      )
852      .await;
853    }
854    let (mut response_parts, response_body) = response.into_parts();
855    if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
856      let custom_headers_hash_iter = custom_headers_hash.iter();
857      for (header_name, header_value) in custom_headers_hash_iter {
858        if let Some(header_name) = header_name.as_str() {
859          if let Some(header_value) = header_value.as_str() {
860            if !response_parts.headers.contains_key(header_name) {
861              if let Ok(header_value) =
862                HeaderValue::from_str(&header_value.replace("{path}", &sanitized_url_pathname))
863              {
864                if let Ok(header_name) = HeaderName::from_str(header_name) {
865                  response_parts.headers.insert(header_name, header_value);
866                }
867              }
868            }
869          }
870        }
871      }
872    }
873    if let Some(http3_alt_port) = http3_alt_port {
874      if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
875        Some(value) => {
876          let header_value_old = String::from_utf8_lossy(value.as_bytes());
877          let header_value_new = format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
878
879          if header_value_old != header_value_new {
880            HeaderValue::from_bytes(format!("{header_value_old}, {header_value_new}").as_bytes())
881          } else {
882            HeaderValue::from_bytes(header_value_old.as_bytes())
883          }
884        }
885        None => HeaderValue::from_bytes(
886          format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
887        ),
888      } {
889        response_parts.headers.insert(header::ALT_SVC, header_value);
890      }
891    }
892    response_parts
893      .headers
894      .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
895
896    return Ok(Response::from_parts(response_parts, response_body));
897  }
898
899  // HTTP-01 ACME challenge for automatic TLS
900  if let Some(acme_http01_resolver) = acme_http01_resolver_option {
901    if let Some(challenge_token) = request
902      .uri()
903      .path()
904      .strip_prefix("/.well-known/acme-challenge/")
905    {
906      if let Some(acme_response) = acme_http01_resolver.get_http_01_key_auth(challenge_token) {
907        let response = Response::builder()
908          .status(StatusCode::OK)
909          .header(
910            CONTENT_TYPE,
911            HeaderValue::from_static("application/octet-stream"),
912          )
913          .body(
914            Full::new(Bytes::from(acme_response))
915              .map_err(|e| match e {})
916              .boxed(),
917          )
918          .unwrap_or_default();
919
920        let (mut response_parts, response_body) = response.into_parts();
921        if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
922          let custom_headers_hash_iter = custom_headers_hash.iter();
923          for (header_name, header_value) in custom_headers_hash_iter {
924            if let Some(header_name) = header_name.as_str() {
925              if let Some(header_value) = header_value.as_str() {
926                if !response_parts.headers.contains_key(header_name) {
927                  if let Ok(header_value) =
928                    HeaderValue::from_str(&header_value.replace("{path}", &sanitized_url_pathname))
929                  {
930                    if let Ok(header_name) = HeaderName::from_str(header_name) {
931                      response_parts.headers.insert(header_name, header_value);
932                    }
933                  }
934                }
935              }
936            }
937          }
938        }
939        if let Some(http3_alt_port) = http3_alt_port {
940          if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
941            Some(value) => {
942              let header_value_old = String::from_utf8_lossy(value.as_bytes());
943              let header_value_new =
944                format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
945
946              if header_value_old != header_value_new {
947                HeaderValue::from_bytes(
948                  format!("{header_value_old}, {header_value_new}").as_bytes(),
949                )
950              } else {
951                HeaderValue::from_bytes(header_value_old.as_bytes())
952              }
953            }
954            None => HeaderValue::from_bytes(
955              format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
956            ),
957          } {
958            response_parts.headers.insert(header::ALT_SVC, header_value);
959          }
960        }
961        response_parts
962          .headers
963          .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
964
965        let response = Response::from_parts(response_parts, response_body);
966
967        if log_enabled {
968          log_combined(
969            &logger,
970            socket_data.remote_addr.ip(),
971            None,
972            log_method,
973            log_request_path,
974            log_protocol,
975            response.status().as_u16(),
976            match response.headers().get(header::CONTENT_LENGTH) {
977              Some(header_value) => match header_value.to_str() {
978                Ok(header_value) => match header_value.parse::<u64>() {
979                  Ok(content_length) => Some(content_length),
980                  Err(_) => response.body().size_hint().exact(),
981                },
982                Err(_) => response.body().size_hint().exact(),
983              },
984              None => response.body().size_hint().exact(),
985            },
986            log_referrer,
987            log_user_agent,
988          )
989          .await;
990        }
991        return Ok(response);
992      }
993    }
994  };
995
996  let cloned_logger = logger.clone();
997  let error_logger = match error_log_enabled {
998    true => ErrorLogger::new(cloned_logger),
999    false => ErrorLogger::without_logger(),
1000  };
1001
1002  if is_connect_proxy_request {
1003    let mut connect_proxy_handlers = None;
1004    for mut handlers in handlers_vec {
1005      if handlers.does_connect_proxy_requests() {
1006        connect_proxy_handlers = Some(handlers);
1007        break;
1008      }
1009    }
1010
1011    if let Some(mut connect_proxy_handlers) = connect_proxy_handlers {
1012      if let Some(connect_address) = request.uri().authority().map(|auth| auth.to_string()) {
1013        // Variables moved to before "tokio::spawn" to avoid issues with moved values
1014        let client_ip = socket_data.remote_addr.ip();
1015        let custom_headers_yaml = combined_config["customHeaders"].clone();
1016
1017        tokio::spawn(async move {
1018          match hyper::upgrade::on(request).await {
1019            Ok(upgraded_request) => {
1020              let result = connect_proxy_handlers
1021                .connect_proxy_request_handler(
1022                  upgraded_request,
1023                  &connect_address,
1024                  &combined_config,
1025                  &socket_data,
1026                  &error_logger,
1027                )
1028                .await;
1029              match result {
1030                Ok(_) => (),
1031                Err(err) => {
1032                  error_logger
1033                    .log(&format!("Unexpected error for CONNECT request: {err}"))
1034                    .await;
1035                }
1036              }
1037            }
1038            Err(err) => {
1039              error_logger
1040                .log(&format!(
1041                  "Error while upgrading HTTP CONNECT request: {err}"
1042                ))
1043                .await
1044            }
1045          }
1046        });
1047
1048        let response = Response::builder()
1049          .body(Empty::new().map_err(|e| match e {}).boxed())
1050          .unwrap_or_default();
1051
1052        if log_enabled {
1053          log_combined(
1054            &logger,
1055            client_ip,
1056            None,
1057            log_method,
1058            log_request_path,
1059            log_protocol,
1060            response.status().as_u16(),
1061            match response.headers().get(header::CONTENT_LENGTH) {
1062              Some(header_value) => match header_value.to_str() {
1063                Ok(header_value) => match header_value.parse::<u64>() {
1064                  Ok(content_length) => Some(content_length),
1065                  Err(_) => response.body().size_hint().exact(),
1066                },
1067                Err(_) => response.body().size_hint().exact(),
1068              },
1069              None => response.body().size_hint().exact(),
1070            },
1071            log_referrer,
1072            log_user_agent,
1073          )
1074          .await;
1075        }
1076
1077        let (mut response_parts, response_body) = response.into_parts();
1078        if let Some(custom_headers_hash) = custom_headers_yaml.as_hash() {
1079          let custom_headers_hash_iter = custom_headers_hash.iter();
1080          for (header_name, header_value) in custom_headers_hash_iter {
1081            if let Some(header_name) = header_name.as_str() {
1082              if let Some(header_value) = header_value.as_str() {
1083                if !response_parts.headers.contains_key(header_name) {
1084                  if let Ok(header_value) =
1085                    HeaderValue::from_str(&header_value.replace("{path}", &sanitized_url_pathname))
1086                  {
1087                    if let Ok(header_name) = HeaderName::from_str(header_name) {
1088                      response_parts.headers.insert(header_name, header_value);
1089                    }
1090                  }
1091                }
1092              }
1093            }
1094          }
1095        }
1096        if let Some(http3_alt_port) = http3_alt_port {
1097          if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
1098            Some(value) => {
1099              let header_value_old = String::from_utf8_lossy(value.as_bytes());
1100              let header_value_new =
1101                format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
1102
1103              if header_value_old != header_value_new {
1104                HeaderValue::from_bytes(
1105                  format!("{header_value_old}, {header_value_new}").as_bytes(),
1106                )
1107              } else {
1108                HeaderValue::from_bytes(header_value_old.as_bytes())
1109              }
1110            }
1111            None => HeaderValue::from_bytes(
1112              format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
1113            ),
1114          } {
1115            response_parts.headers.insert(header::ALT_SVC, header_value);
1116          }
1117        }
1118        response_parts
1119          .headers
1120          .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
1121
1122        Ok(Response::from_parts(response_parts, response_body))
1123      } else {
1124        let response = Response::builder()
1125          .status(StatusCode::BAD_REQUEST)
1126          .body(Empty::new().map_err(|e| match e {}).boxed())
1127          .unwrap_or_default();
1128
1129        if log_enabled {
1130          log_combined(
1131            &logger,
1132            socket_data.remote_addr.ip(),
1133            None,
1134            log_method,
1135            log_request_path,
1136            log_protocol,
1137            response.status().as_u16(),
1138            match response.headers().get(header::CONTENT_LENGTH) {
1139              Some(header_value) => match header_value.to_str() {
1140                Ok(header_value) => match header_value.parse::<u64>() {
1141                  Ok(content_length) => Some(content_length),
1142                  Err(_) => response.body().size_hint().exact(),
1143                },
1144                Err(_) => response.body().size_hint().exact(),
1145              },
1146              None => response.body().size_hint().exact(),
1147            },
1148            log_referrer,
1149            log_user_agent,
1150          )
1151          .await;
1152        }
1153        let (mut response_parts, response_body) = response.into_parts();
1154        if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
1155          let custom_headers_hash_iter = custom_headers_hash.iter();
1156          for (header_name, header_value) in custom_headers_hash_iter {
1157            if let Some(header_name) = header_name.as_str() {
1158              if let Some(header_value) = header_value.as_str() {
1159                if !response_parts.headers.contains_key(header_name) {
1160                  if let Ok(header_value) =
1161                    HeaderValue::from_str(&header_value.replace("{path}", &sanitized_url_pathname))
1162                  {
1163                    if let Ok(header_name) = HeaderName::from_str(header_name) {
1164                      response_parts.headers.insert(header_name, header_value);
1165                    }
1166                  }
1167                }
1168              }
1169            }
1170          }
1171        }
1172        if let Some(http3_alt_port) = http3_alt_port {
1173          if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
1174            Some(value) => {
1175              let header_value_old = String::from_utf8_lossy(value.as_bytes());
1176              let header_value_new =
1177                format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
1178
1179              if header_value_old != header_value_new {
1180                HeaderValue::from_bytes(
1181                  format!("{header_value_old}, {header_value_new}").as_bytes(),
1182                )
1183              } else {
1184                HeaderValue::from_bytes(header_value_old.as_bytes())
1185              }
1186            }
1187            None => HeaderValue::from_bytes(
1188              format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
1189            ),
1190          } {
1191            response_parts.headers.insert(header::ALT_SVC, header_value);
1192          }
1193        }
1194        response_parts
1195          .headers
1196          .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
1197
1198        Ok(Response::from_parts(response_parts, response_body))
1199      }
1200    } else {
1201      let response = Response::builder()
1202        .status(StatusCode::NOT_IMPLEMENTED)
1203        .body(Empty::new().map_err(|e| match e {}).boxed())
1204        .unwrap_or_default();
1205
1206      if log_enabled {
1207        log_combined(
1208          &logger,
1209          socket_data.remote_addr.ip(),
1210          None,
1211          log_method,
1212          log_request_path,
1213          log_protocol,
1214          response.status().as_u16(),
1215          match response.headers().get(header::CONTENT_LENGTH) {
1216            Some(header_value) => match header_value.to_str() {
1217              Ok(header_value) => match header_value.parse::<u64>() {
1218                Ok(content_length) => Some(content_length),
1219                Err(_) => response.body().size_hint().exact(),
1220              },
1221              Err(_) => response.body().size_hint().exact(),
1222            },
1223            None => response.body().size_hint().exact(),
1224          },
1225          log_referrer,
1226          log_user_agent,
1227        )
1228        .await;
1229      }
1230      let (mut response_parts, response_body) = response.into_parts();
1231      if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
1232        let custom_headers_hash_iter = custom_headers_hash.iter();
1233        for (header_name, header_value) in custom_headers_hash_iter {
1234          if let Some(header_name) = header_name.as_str() {
1235            if let Some(header_value) = header_value.as_str() {
1236              if !response_parts.headers.contains_key(header_name) {
1237                if let Ok(header_value) =
1238                  HeaderValue::from_str(&header_value.replace("{path}", &sanitized_url_pathname))
1239                {
1240                  if let Ok(header_name) = HeaderName::from_str(header_name) {
1241                    response_parts.headers.insert(header_name, header_value);
1242                  }
1243                }
1244              }
1245            }
1246          }
1247        }
1248      }
1249      if let Some(http3_alt_port) = http3_alt_port {
1250        if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
1251          Some(value) => {
1252            let header_value_old = String::from_utf8_lossy(value.as_bytes());
1253            let header_value_new = format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
1254
1255            if header_value_old != header_value_new {
1256              HeaderValue::from_bytes(format!("{header_value_old}, {header_value_new}").as_bytes())
1257            } else {
1258              HeaderValue::from_bytes(header_value_old.as_bytes())
1259            }
1260          }
1261          None => HeaderValue::from_bytes(
1262            format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
1263          ),
1264        } {
1265          response_parts.headers.insert(header::ALT_SVC, header_value);
1266        }
1267      }
1268      response_parts
1269        .headers
1270        .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
1271
1272      Ok(Response::from_parts(response_parts, response_body))
1273    }
1274  } else {
1275    let is_websocket_request = is_upgrade_request(&request);
1276    let (request_parts, request_body) = request.into_parts();
1277    let request_parts_cloned = if combined_config["errorConfig"].is_array() {
1278      let mut request_parts_cloned = request_parts.clone();
1279      request_parts_cloned
1280        .headers
1281        .insert(header::CONTENT_LENGTH, HeaderValue::from_static("0"));
1282      Some(request_parts_cloned)
1283    } else {
1284      // If the error configuration is not specified, don't clone the request parts to improve performance
1285      None
1286    };
1287    let request = Request::from_parts(request_parts, request_body);
1288    let mut request_data = RequestData::new(request, None, None, None);
1289    let mut latest_auth_data = None;
1290    let mut error_status_code = None;
1291    let mut executed_handlers = Vec::new();
1292    let mut handlers_iter: Box<
1293      dyn Iterator<Item = Box<dyn ServerModuleHandlers + Send + 'static>> + Send,
1294    > = Box::new(handlers_vec.into_iter());
1295    while let Some(mut handlers) = handlers_iter.next() {
1296      if is_websocket_request && handlers.does_websocket_requests(&combined_config, &socket_data) {
1297        let (request, _, _, _) = request_data.into_parts();
1298
1299        // Variables moved to before "tokio::spawn" to avoid issues with moved values
1300        let client_ip = socket_data.remote_addr.ip();
1301        let custom_headers_yaml = combined_config["customHeaders"].clone();
1302        let request_uri = request.uri().to_owned();
1303        let request_headers = request.headers().to_owned();
1304
1305        let (original_response, websocket) = match hyper_tungstenite::upgrade(request, None) {
1306          Ok(data) => data,
1307          Err(err) => {
1308            error_logger
1309              .log(&format!("Error while upgrading WebSocket request: {err}"))
1310              .await;
1311
1312            let response = Response::builder()
1313              .status(StatusCode::INTERNAL_SERVER_ERROR)
1314              .body(
1315                Full::new(Bytes::from(generate_default_error_page(
1316                  StatusCode::INTERNAL_SERVER_ERROR,
1317                  None,
1318                )))
1319                .map_err(|e| match e {})
1320                .boxed(),
1321              )
1322              .unwrap_or_default();
1323
1324            if log_enabled {
1325              log_combined(
1326                &logger,
1327                socket_data.remote_addr.ip(),
1328                None,
1329                log_method,
1330                log_request_path,
1331                log_protocol,
1332                response.status().as_u16(),
1333                match response.headers().get(header::CONTENT_LENGTH) {
1334                  Some(header_value) => match header_value.to_str() {
1335                    Ok(header_value) => match header_value.parse::<u64>() {
1336                      Ok(content_length) => Some(content_length),
1337                      Err(_) => response.body().size_hint().exact(),
1338                    },
1339                    Err(_) => response.body().size_hint().exact(),
1340                  },
1341                  None => response.body().size_hint().exact(),
1342                },
1343                log_referrer,
1344                log_user_agent,
1345              )
1346              .await;
1347            }
1348            let (mut response_parts, response_body) = response.into_parts();
1349            if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
1350              let custom_headers_hash_iter = custom_headers_hash.iter();
1351              for (header_name, header_value) in custom_headers_hash_iter {
1352                if let Some(header_name) = header_name.as_str() {
1353                  if let Some(header_value) = header_value.as_str() {
1354                    if !response_parts.headers.contains_key(header_name) {
1355                      if let Ok(header_value) = HeaderValue::from_str(
1356                        &header_value.replace("{path}", &sanitized_url_pathname),
1357                      ) {
1358                        if let Ok(header_name) = HeaderName::from_str(header_name) {
1359                          response_parts.headers.insert(header_name, header_value);
1360                        }
1361                      }
1362                    }
1363                  }
1364                }
1365              }
1366            }
1367            if let Some(http3_alt_port) = http3_alt_port {
1368              if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
1369                Some(value) => {
1370                  let header_value_old = String::from_utf8_lossy(value.as_bytes());
1371                  let header_value_new =
1372                    format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
1373
1374                  if header_value_old != header_value_new {
1375                    HeaderValue::from_bytes(
1376                      format!("{header_value_old}, {header_value_new}").as_bytes(),
1377                    )
1378                  } else {
1379                    HeaderValue::from_bytes(header_value_old.as_bytes())
1380                  }
1381                }
1382                None => HeaderValue::from_bytes(
1383                  format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
1384                ),
1385              } {
1386                response_parts.headers.insert(header::ALT_SVC, header_value);
1387              }
1388            }
1389            response_parts
1390              .headers
1391              .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
1392
1393            return Ok(Response::from_parts(response_parts, response_body));
1394          }
1395        };
1396
1397        tokio::spawn(async move {
1398          let result = handlers
1399            .websocket_request_handler(
1400              websocket,
1401              &request_uri,
1402              &request_headers,
1403              &combined_config,
1404              &socket_data,
1405              &error_logger,
1406            )
1407            .await;
1408          match result {
1409            Ok(_) => (),
1410            Err(err) => {
1411              error_logger
1412                .log(&format!("Unexpected error for WebSocket request: {err}"))
1413                .await;
1414            }
1415          }
1416        });
1417
1418        let response = original_response.map(|body| body.map_err(|err| match err {}).boxed());
1419
1420        if log_enabled {
1421          log_combined(
1422            &logger,
1423            client_ip,
1424            None,
1425            log_method,
1426            log_request_path,
1427            log_protocol,
1428            response.status().as_u16(),
1429            match response.headers().get(header::CONTENT_LENGTH) {
1430              Some(header_value) => match header_value.to_str() {
1431                Ok(header_value) => match header_value.parse::<u64>() {
1432                  Ok(content_length) => Some(content_length),
1433                  Err(_) => response.body().size_hint().exact(),
1434                },
1435                Err(_) => response.body().size_hint().exact(),
1436              },
1437              None => response.body().size_hint().exact(),
1438            },
1439            log_referrer,
1440            log_user_agent,
1441          )
1442          .await;
1443        }
1444
1445        let (mut response_parts, response_body) = response.into_parts();
1446        if let Some(custom_headers_hash) = custom_headers_yaml.as_hash() {
1447          let custom_headers_hash_iter = custom_headers_hash.iter();
1448          for (header_name, header_value) in custom_headers_hash_iter {
1449            if let Some(header_name) = header_name.as_str() {
1450              if let Some(header_value) = header_value.as_str() {
1451                if !response_parts.headers.contains_key(header_name) {
1452                  if let Ok(header_value) =
1453                    HeaderValue::from_str(&header_value.replace("{path}", &sanitized_url_pathname))
1454                  {
1455                    if let Ok(header_name) = HeaderName::from_str(header_name) {
1456                      response_parts.headers.insert(header_name, header_value);
1457                    }
1458                  }
1459                }
1460              }
1461            }
1462          }
1463        }
1464        if let Some(http3_alt_port) = http3_alt_port {
1465          if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
1466            Some(value) => {
1467              let header_value_old = String::from_utf8_lossy(value.as_bytes());
1468              let header_value_new =
1469                format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
1470
1471              if header_value_old != header_value_new {
1472                HeaderValue::from_bytes(
1473                  format!("{header_value_old}, {header_value_new}").as_bytes(),
1474                )
1475              } else {
1476                HeaderValue::from_bytes(header_value_old.as_bytes())
1477              }
1478            }
1479            None => HeaderValue::from_bytes(
1480              format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
1481            ),
1482          } {
1483            response_parts.headers.insert(header::ALT_SVC, header_value);
1484          }
1485        }
1486        response_parts
1487          .headers
1488          .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
1489
1490        return Ok(Response::from_parts(response_parts, response_body));
1491      }
1492
1493      let response_result = match is_proxy_request {
1494        true => {
1495          handlers
1496            .proxy_request_handler(request_data, &combined_config, &socket_data, &error_logger)
1497            .await
1498        }
1499        false => {
1500          handlers
1501            .request_handler(request_data, &combined_config, &socket_data, &error_logger)
1502            .await
1503        }
1504      };
1505
1506      executed_handlers.push(handlers);
1507      match response_result {
1508        Ok(response) => {
1509          let (
1510            request_option,
1511            auth_data,
1512            original_url,
1513            response,
1514            status,
1515            headers,
1516            new_remote_address,
1517            parallel_fn,
1518          ) = response.into_parts();
1519          latest_auth_data = auth_data.clone();
1520          if let Some(new_remote_address) = new_remote_address {
1521            socket_data.remote_addr = new_remote_address;
1522          };
1523          if let Some(parallel_fn) = parallel_fn {
1524            // Spawn the function in the web server's Tokio runtime.
1525            // We have implemented parallel_fn parameter in the ResponseData
1526            // because tokio::spawn doesn't work on dynamic libraries,
1527            // see https://github.com/tokio-rs/tokio/issues/6927
1528            tokio::spawn(parallel_fn);
1529          }
1530          match response {
1531            Some(response) => {
1532              let (mut response_parts, response_body) = response.into_parts();
1533              if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
1534                let custom_headers_hash_iter = custom_headers_hash.iter();
1535                for (header_name, header_value) in custom_headers_hash_iter {
1536                  if let Some(header_name) = header_name.as_str() {
1537                    if let Some(header_value) = header_value.as_str() {
1538                      if !response_parts.headers.contains_key(header_name) {
1539                        if let Ok(header_value) = HeaderValue::from_str(
1540                          &header_value.replace("{path}", &sanitized_url_pathname),
1541                        ) {
1542                          if let Ok(header_name) = HeaderName::from_str(header_name) {
1543                            response_parts.headers.insert(header_name, header_value);
1544                          }
1545                        }
1546                      }
1547                    }
1548                  }
1549                }
1550              }
1551              if let Some(http3_alt_port) = http3_alt_port {
1552                if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
1553                  Some(value) => {
1554                    let header_value_old = String::from_utf8_lossy(value.as_bytes());
1555                    let header_value_new =
1556                      format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
1557
1558                    if header_value_old != header_value_new {
1559                      HeaderValue::from_bytes(
1560                        format!("{header_value_old}, {header_value_new}").as_bytes(),
1561                      )
1562                    } else {
1563                      HeaderValue::from_bytes(header_value_old.as_bytes())
1564                    }
1565                  }
1566                  None => HeaderValue::from_bytes(
1567                    format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
1568                  ),
1569                } {
1570                  response_parts.headers.insert(header::ALT_SVC, header_value);
1571                }
1572              }
1573              response_parts
1574                .headers
1575                .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
1576
1577              let mut response = Response::from_parts(response_parts, response_body);
1578
1579              while let Some(mut executed_handler) = executed_handlers.pop() {
1580                let response_status = match is_proxy_request {
1581                  true => {
1582                    executed_handler
1583                      .proxy_response_modifying_handler(response)
1584                      .await
1585                  }
1586                  false => executed_handler.response_modifying_handler(response).await,
1587                };
1588                response = match response_status {
1589                  Ok(response) => response,
1590                  Err(err) => {
1591                    if error_log_enabled {
1592                      logger
1593                        .send(LogMessage::new(
1594                          format!("Unexpected error while serving a request: {err}"),
1595                          true,
1596                        ))
1597                        .await
1598                        .unwrap_or_default();
1599                    }
1600
1601                    let response = generate_error_response(
1602                      StatusCode::INTERNAL_SERVER_ERROR,
1603                      &combined_config,
1604                      &headers,
1605                    )
1606                    .await;
1607                    if log_enabled {
1608                      log_combined(
1609                        &logger,
1610                        socket_data.remote_addr.ip(),
1611                        auth_data,
1612                        log_method,
1613                        log_request_path,
1614                        log_protocol,
1615                        response.status().as_u16(),
1616                        match response.headers().get(header::CONTENT_LENGTH) {
1617                          Some(header_value) => match header_value.to_str() {
1618                            Ok(header_value) => match header_value.parse::<u64>() {
1619                              Ok(content_length) => Some(content_length),
1620                              Err(_) => response.body().size_hint().exact(),
1621                            },
1622                            Err(_) => response.body().size_hint().exact(),
1623                          },
1624                          None => response.body().size_hint().exact(),
1625                        },
1626                        log_referrer,
1627                        log_user_agent,
1628                      )
1629                      .await;
1630                    }
1631                    let (mut response_parts, response_body) = response.into_parts();
1632                    if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
1633                      let custom_headers_hash_iter = custom_headers_hash.iter();
1634                      for (header_name, header_value) in custom_headers_hash_iter {
1635                        if let Some(header_name) = header_name.as_str() {
1636                          if let Some(header_value) = header_value.as_str() {
1637                            if !response_parts.headers.contains_key(header_name) {
1638                              if let Ok(header_value) = HeaderValue::from_str(
1639                                &header_value.replace("{path}", &sanitized_url_pathname),
1640                              ) {
1641                                if let Ok(header_name) = HeaderName::from_str(header_name) {
1642                                  response_parts.headers.insert(header_name, header_value);
1643                                }
1644                              }
1645                            }
1646                          }
1647                        }
1648                      }
1649                    }
1650                    if let Some(http3_alt_port) = http3_alt_port {
1651                      if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
1652                        Some(value) => {
1653                          let header_value_old = String::from_utf8_lossy(value.as_bytes());
1654                          let header_value_new =
1655                            format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
1656
1657                          if header_value_old != header_value_new {
1658                            HeaderValue::from_bytes(
1659                              format!("{header_value_old}, {header_value_new}").as_bytes(),
1660                            )
1661                          } else {
1662                            HeaderValue::from_bytes(header_value_old.as_bytes())
1663                          }
1664                        }
1665                        None => HeaderValue::from_bytes(
1666                          format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"")
1667                            .as_bytes(),
1668                        ),
1669                      } {
1670                        response_parts.headers.insert(header::ALT_SVC, header_value);
1671                      }
1672                    }
1673                    response_parts
1674                      .headers
1675                      .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
1676
1677                    return Ok(Response::from_parts(response_parts, response_body));
1678                  }
1679                };
1680              }
1681
1682              if log_enabled {
1683                log_combined(
1684                  &logger,
1685                  socket_data.remote_addr.ip(),
1686                  auth_data,
1687                  log_method,
1688                  log_request_path,
1689                  log_protocol,
1690                  response.status().as_u16(),
1691                  match response.headers().get(header::CONTENT_LENGTH) {
1692                    Some(header_value) => match header_value.to_str() {
1693                      Ok(header_value) => match header_value.parse::<u64>() {
1694                        Ok(content_length) => Some(content_length),
1695                        Err(_) => response.body().size_hint().exact(),
1696                      },
1697                      Err(_) => response.body().size_hint().exact(),
1698                    },
1699                    None => response.body().size_hint().exact(),
1700                  },
1701                  log_referrer,
1702                  log_user_agent,
1703                )
1704                .await;
1705              }
1706
1707              return Ok(response);
1708            }
1709            None => match status {
1710              Some(status) => {
1711                let request = if let Some(request) = request_option {
1712                  Some(request)
1713                } else {
1714                  request_parts_cloned.clone().map(|request_parts_cloned| {
1715                    Request::from_parts(
1716                      request_parts_cloned,
1717                      Empty::new().map_err(|e| match e {}).boxed(),
1718                    )
1719                  })
1720                };
1721                if let Some(request) = request {
1722                  if let Some(combined_error_config) =
1723                    combine_error_config(&combined_config, status.as_u16())
1724                  {
1725                    combined_config = combined_error_config;
1726                    error_status_code = Some(status);
1727                    handlers_iter = Box::new(executed_handlers.into_iter().chain(handlers_iter));
1728                    executed_handlers = Vec::new();
1729                    request_data =
1730                      RequestData::new(request, auth_data, original_url, error_status_code);
1731                    continue;
1732                  }
1733                }
1734                let response = generate_error_response(status, &combined_config, &headers).await;
1735                let (mut response_parts, response_body) = response.into_parts();
1736                if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
1737                  let custom_headers_hash_iter = custom_headers_hash.iter();
1738                  for (header_name, header_value) in custom_headers_hash_iter {
1739                    if let Some(header_name) = header_name.as_str() {
1740                      if let Some(header_value) = header_value.as_str() {
1741                        if !response_parts.headers.contains_key(header_name) {
1742                          if let Ok(header_value) = HeaderValue::from_str(
1743                            &header_value.replace("{path}", &sanitized_url_pathname),
1744                          ) {
1745                            if let Ok(header_name) = HeaderName::from_str(header_name) {
1746                              response_parts.headers.insert(header_name, header_value);
1747                            }
1748                          }
1749                        }
1750                      }
1751                    }
1752                  }
1753                }
1754                if let Some(http3_alt_port) = http3_alt_port {
1755                  if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
1756                    Some(value) => {
1757                      let header_value_old = String::from_utf8_lossy(value.as_bytes());
1758                      let header_value_new =
1759                        format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
1760
1761                      if header_value_old != header_value_new {
1762                        HeaderValue::from_bytes(
1763                          format!("{header_value_old}, {header_value_new}").as_bytes(),
1764                        )
1765                      } else {
1766                        HeaderValue::from_bytes(header_value_old.as_bytes())
1767                      }
1768                    }
1769                    None => HeaderValue::from_bytes(
1770                      format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
1771                    ),
1772                  } {
1773                    response_parts.headers.insert(header::ALT_SVC, header_value);
1774                  }
1775                }
1776                response_parts
1777                  .headers
1778                  .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
1779
1780                let mut response = Response::from_parts(response_parts, response_body);
1781
1782                while let Some(mut executed_handler) = executed_handlers.pop() {
1783                  let response_status = match is_proxy_request {
1784                    true => {
1785                      executed_handler
1786                        .proxy_response_modifying_handler(response)
1787                        .await
1788                    }
1789                    false => executed_handler.response_modifying_handler(response).await,
1790                  };
1791                  response = match response_status {
1792                    Ok(response) => response,
1793                    Err(err) => {
1794                      if error_log_enabled {
1795                        logger
1796                          .send(LogMessage::new(
1797                            format!("Unexpected error while serving a request: {err}"),
1798                            true,
1799                          ))
1800                          .await
1801                          .unwrap_or_default();
1802                      }
1803
1804                      let response = generate_error_response(
1805                        StatusCode::INTERNAL_SERVER_ERROR,
1806                        &combined_config,
1807                        &headers,
1808                      )
1809                      .await;
1810                      if log_enabled {
1811                        log_combined(
1812                          &logger,
1813                          socket_data.remote_addr.ip(),
1814                          auth_data,
1815                          log_method,
1816                          log_request_path,
1817                          log_protocol,
1818                          response.status().as_u16(),
1819                          match response.headers().get(header::CONTENT_LENGTH) {
1820                            Some(header_value) => match header_value.to_str() {
1821                              Ok(header_value) => match header_value.parse::<u64>() {
1822                                Ok(content_length) => Some(content_length),
1823                                Err(_) => response.body().size_hint().exact(),
1824                              },
1825                              Err(_) => response.body().size_hint().exact(),
1826                            },
1827                            None => response.body().size_hint().exact(),
1828                          },
1829                          log_referrer,
1830                          log_user_agent,
1831                        )
1832                        .await;
1833                      }
1834                      let (mut response_parts, response_body) = response.into_parts();
1835                      if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash()
1836                      {
1837                        let custom_headers_hash_iter = custom_headers_hash.iter();
1838                        for (header_name, header_value) in custom_headers_hash_iter {
1839                          if let Some(header_name) = header_name.as_str() {
1840                            if let Some(header_value) = header_value.as_str() {
1841                              if !response_parts.headers.contains_key(header_name) {
1842                                if let Ok(header_value) = HeaderValue::from_str(
1843                                  &header_value.replace("{path}", &sanitized_url_pathname),
1844                                ) {
1845                                  if let Ok(header_name) = HeaderName::from_str(header_name) {
1846                                    response_parts.headers.insert(header_name, header_value);
1847                                  }
1848                                }
1849                              }
1850                            }
1851                          }
1852                        }
1853                      }
1854                      if let Some(http3_alt_port) = http3_alt_port {
1855                        if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC)
1856                        {
1857                          Some(value) => {
1858                            let header_value_old = String::from_utf8_lossy(value.as_bytes());
1859                            let header_value_new =
1860                              format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
1861
1862                            if header_value_old != header_value_new {
1863                              HeaderValue::from_bytes(
1864                                format!("{header_value_old}, {header_value_new}").as_bytes(),
1865                              )
1866                            } else {
1867                              HeaderValue::from_bytes(header_value_old.as_bytes())
1868                            }
1869                          }
1870                          None => HeaderValue::from_bytes(
1871                            format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"")
1872                              .as_bytes(),
1873                          ),
1874                        } {
1875                          response_parts.headers.insert(header::ALT_SVC, header_value);
1876                        }
1877                      }
1878                      response_parts
1879                        .headers
1880                        .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
1881
1882                      return Ok(Response::from_parts(response_parts, response_body));
1883                    }
1884                  };
1885                }
1886
1887                if log_enabled {
1888                  log_combined(
1889                    &logger,
1890                    socket_data.remote_addr.ip(),
1891                    auth_data,
1892                    log_method,
1893                    log_request_path,
1894                    log_protocol,
1895                    response.status().as_u16(),
1896                    match response.headers().get(header::CONTENT_LENGTH) {
1897                      Some(header_value) => match header_value.to_str() {
1898                        Ok(header_value) => match header_value.parse::<u64>() {
1899                          Ok(content_length) => Some(content_length),
1900                          Err(_) => response.body().size_hint().exact(),
1901                        },
1902                        Err(_) => response.body().size_hint().exact(),
1903                      },
1904                      None => response.body().size_hint().exact(),
1905                    },
1906                    log_referrer,
1907                    log_user_agent,
1908                  )
1909                  .await;
1910                }
1911                return Ok(response);
1912              }
1913              None => match request_option {
1914                Some(request) => {
1915                  request_data =
1916                    RequestData::new(request, auth_data, original_url, error_status_code);
1917                  continue;
1918                }
1919                None => {
1920                  break;
1921                }
1922              },
1923            },
1924          }
1925        }
1926        Err(err) => {
1927          let response =
1928            generate_error_response(StatusCode::INTERNAL_SERVER_ERROR, &combined_config, &None)
1929              .await;
1930
1931          let (mut response_parts, response_body) = response.into_parts();
1932          if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
1933            let custom_headers_hash_iter = custom_headers_hash.iter();
1934            for (header_name, header_value) in custom_headers_hash_iter {
1935              if let Some(header_name) = header_name.as_str() {
1936                if let Some(header_value) = header_value.as_str() {
1937                  if !response_parts.headers.contains_key(header_name) {
1938                    if let Ok(header_value) = HeaderValue::from_str(
1939                      &header_value.replace("{path}", &sanitized_url_pathname),
1940                    ) {
1941                      if let Ok(header_name) = HeaderName::from_str(header_name) {
1942                        response_parts.headers.insert(header_name, header_value);
1943                      }
1944                    }
1945                  }
1946                }
1947              }
1948            }
1949          }
1950          if let Some(http3_alt_port) = http3_alt_port {
1951            if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
1952              Some(value) => {
1953                let header_value_old = String::from_utf8_lossy(value.as_bytes());
1954                let header_value_new =
1955                  format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
1956
1957                if header_value_old != header_value_new {
1958                  HeaderValue::from_bytes(
1959                    format!("{header_value_old}, {header_value_new}").as_bytes(),
1960                  )
1961                } else {
1962                  HeaderValue::from_bytes(header_value_old.as_bytes())
1963                }
1964              }
1965              None => HeaderValue::from_bytes(
1966                format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
1967              ),
1968            } {
1969              response_parts.headers.insert(header::ALT_SVC, header_value);
1970            }
1971          }
1972          response_parts
1973            .headers
1974            .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
1975
1976          let mut response = Response::from_parts(response_parts, response_body);
1977
1978          while let Some(mut executed_handler) = executed_handlers.pop() {
1979            let response_status = match is_proxy_request {
1980              true => {
1981                executed_handler
1982                  .proxy_response_modifying_handler(response)
1983                  .await
1984              }
1985              false => executed_handler.response_modifying_handler(response).await,
1986            };
1987            response = match response_status {
1988              Ok(response) => response,
1989              Err(err) => {
1990                if error_log_enabled {
1991                  logger
1992                    .send(LogMessage::new(
1993                      format!("Unexpected error while serving a request: {err}"),
1994                      true,
1995                    ))
1996                    .await
1997                    .unwrap_or_default();
1998                }
1999
2000                let response = generate_error_response(
2001                  StatusCode::INTERNAL_SERVER_ERROR,
2002                  &combined_config,
2003                  &None,
2004                )
2005                .await;
2006                if log_enabled {
2007                  log_combined(
2008                    &logger,
2009                    socket_data.remote_addr.ip(),
2010                    latest_auth_data,
2011                    log_method,
2012                    log_request_path,
2013                    log_protocol,
2014                    response.status().as_u16(),
2015                    match response.headers().get(header::CONTENT_LENGTH) {
2016                      Some(header_value) => match header_value.to_str() {
2017                        Ok(header_value) => match header_value.parse::<u64>() {
2018                          Ok(content_length) => Some(content_length),
2019                          Err(_) => response.body().size_hint().exact(),
2020                        },
2021                        Err(_) => response.body().size_hint().exact(),
2022                      },
2023                      None => response.body().size_hint().exact(),
2024                    },
2025                    log_referrer,
2026                    log_user_agent,
2027                  )
2028                  .await;
2029                }
2030                let (mut response_parts, response_body) = response.into_parts();
2031                if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
2032                  let custom_headers_hash_iter = custom_headers_hash.iter();
2033                  for (header_name, header_value) in custom_headers_hash_iter {
2034                    if let Some(header_name) = header_name.as_str() {
2035                      if let Some(header_value) = header_value.as_str() {
2036                        if !response_parts.headers.contains_key(header_name) {
2037                          if let Ok(header_value) = HeaderValue::from_str(
2038                            &header_value.replace("{path}", &sanitized_url_pathname),
2039                          ) {
2040                            if let Ok(header_name) = HeaderName::from_str(header_name) {
2041                              response_parts.headers.insert(header_name, header_value);
2042                            }
2043                          }
2044                        }
2045                      }
2046                    }
2047                  }
2048                }
2049                if let Some(http3_alt_port) = http3_alt_port {
2050                  if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
2051                    Some(value) => {
2052                      let header_value_old = String::from_utf8_lossy(value.as_bytes());
2053                      let header_value_new =
2054                        format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
2055
2056                      if header_value_old != header_value_new {
2057                        HeaderValue::from_bytes(
2058                          format!("{header_value_old}, {header_value_new}").as_bytes(),
2059                        )
2060                      } else {
2061                        HeaderValue::from_bytes(header_value_old.as_bytes())
2062                      }
2063                    }
2064                    None => HeaderValue::from_bytes(
2065                      format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
2066                    ),
2067                  } {
2068                    response_parts.headers.insert(header::ALT_SVC, header_value);
2069                  }
2070                }
2071                response_parts
2072                  .headers
2073                  .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
2074
2075                return Ok(Response::from_parts(response_parts, response_body));
2076              }
2077            };
2078          }
2079
2080          if error_log_enabled {
2081            logger
2082              .send(LogMessage::new(
2083                format!("Unexpected error while serving a request: {err}"),
2084                true,
2085              ))
2086              .await
2087              .unwrap_or_default();
2088          }
2089
2090          if log_enabled {
2091            log_combined(
2092              &logger,
2093              socket_data.remote_addr.ip(),
2094              latest_auth_data,
2095              log_method,
2096              log_request_path,
2097              log_protocol,
2098              response.status().as_u16(),
2099              match response.headers().get(header::CONTENT_LENGTH) {
2100                Some(header_value) => match header_value.to_str() {
2101                  Ok(header_value) => match header_value.parse::<u64>() {
2102                    Ok(content_length) => Some(content_length),
2103                    Err(_) => response.body().size_hint().exact(),
2104                  },
2105                  Err(_) => response.body().size_hint().exact(),
2106                },
2107                None => response.body().size_hint().exact(),
2108              },
2109              log_referrer,
2110              log_user_agent,
2111            )
2112            .await;
2113          }
2114          return Ok(response);
2115        }
2116      }
2117    }
2118
2119    let response = generate_error_response(StatusCode::NOT_FOUND, &combined_config, &None).await;
2120
2121    let (mut response_parts, response_body) = response.into_parts();
2122    if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
2123      let custom_headers_hash_iter = custom_headers_hash.iter();
2124      for (header_name, header_value) in custom_headers_hash_iter {
2125        if let Some(header_name) = header_name.as_str() {
2126          if let Some(header_value) = header_value.as_str() {
2127            if !response_parts.headers.contains_key(header_name) {
2128              if let Ok(header_value) =
2129                HeaderValue::from_str(&header_value.replace("{path}", &sanitized_url_pathname))
2130              {
2131                if let Ok(header_name) = HeaderName::from_str(header_name) {
2132                  response_parts.headers.insert(header_name, header_value);
2133                }
2134              }
2135            }
2136          }
2137        }
2138      }
2139    }
2140    if let Some(http3_alt_port) = http3_alt_port {
2141      if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
2142        Some(value) => {
2143          let header_value_old = String::from_utf8_lossy(value.as_bytes());
2144          let header_value_new = format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
2145
2146          if header_value_old != header_value_new {
2147            HeaderValue::from_bytes(format!("{header_value_old}, {header_value_new}").as_bytes())
2148          } else {
2149            HeaderValue::from_bytes(header_value_old.as_bytes())
2150          }
2151        }
2152        None => HeaderValue::from_bytes(
2153          format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
2154        ),
2155      } {
2156        response_parts.headers.insert(header::ALT_SVC, header_value);
2157      }
2158    }
2159    response_parts
2160      .headers
2161      .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
2162
2163    let mut response = Response::from_parts(response_parts, response_body);
2164
2165    while let Some(mut executed_handler) = executed_handlers.pop() {
2166      let response_status = match is_proxy_request {
2167        true => {
2168          executed_handler
2169            .proxy_response_modifying_handler(response)
2170            .await
2171        }
2172        false => executed_handler.response_modifying_handler(response).await,
2173      };
2174      response = match response_status {
2175        Ok(response) => response,
2176        Err(err) => {
2177          if error_log_enabled {
2178            logger
2179              .send(LogMessage::new(
2180                format!("Unexpected error while serving a request: {err}"),
2181                true,
2182              ))
2183              .await
2184              .unwrap_or_default();
2185          }
2186
2187          let response =
2188            generate_error_response(StatusCode::INTERNAL_SERVER_ERROR, &combined_config, &None)
2189              .await;
2190          if log_enabled {
2191            log_combined(
2192              &logger,
2193              socket_data.remote_addr.ip(),
2194              latest_auth_data,
2195              log_method,
2196              log_request_path,
2197              log_protocol,
2198              response.status().as_u16(),
2199              match response.headers().get(header::CONTENT_LENGTH) {
2200                Some(header_value) => match header_value.to_str() {
2201                  Ok(header_value) => match header_value.parse::<u64>() {
2202                    Ok(content_length) => Some(content_length),
2203                    Err(_) => response.body().size_hint().exact(),
2204                  },
2205                  Err(_) => response.body().size_hint().exact(),
2206                },
2207                None => response.body().size_hint().exact(),
2208              },
2209              log_referrer,
2210              log_user_agent,
2211            )
2212            .await;
2213          }
2214          let (mut response_parts, response_body) = response.into_parts();
2215          if let Some(custom_headers_hash) = combined_config["customHeaders"].as_hash() {
2216            let custom_headers_hash_iter = custom_headers_hash.iter();
2217            for (header_name, header_value) in custom_headers_hash_iter {
2218              if let Some(header_name) = header_name.as_str() {
2219                if let Some(header_value) = header_value.as_str() {
2220                  if !response_parts.headers.contains_key(header_name) {
2221                    if let Ok(header_value) = HeaderValue::from_str(
2222                      &header_value.replace("{path}", &sanitized_url_pathname),
2223                    ) {
2224                      if let Ok(header_name) = HeaderName::from_str(header_name) {
2225                        response_parts.headers.insert(header_name, header_value);
2226                      }
2227                    }
2228                  }
2229                }
2230              }
2231            }
2232          }
2233          if let Some(http3_alt_port) = http3_alt_port {
2234            if let Ok(header_value) = match response_parts.headers.get(header::ALT_SVC) {
2235              Some(value) => {
2236                let header_value_old = String::from_utf8_lossy(value.as_bytes());
2237                let header_value_new =
2238                  format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"");
2239
2240                if header_value_old != header_value_new {
2241                  HeaderValue::from_bytes(
2242                    format!("{header_value_old}, {header_value_new}").as_bytes(),
2243                  )
2244                } else {
2245                  HeaderValue::from_bytes(header_value_old.as_bytes())
2246                }
2247              }
2248              None => HeaderValue::from_bytes(
2249                format!("h3=\":{http3_alt_port}\", h3-29=\":{http3_alt_port}\"").as_bytes(),
2250              ),
2251            } {
2252              response_parts.headers.insert(header::ALT_SVC, header_value);
2253            }
2254          }
2255          response_parts
2256            .headers
2257            .insert(header::SERVER, HeaderValue::from_static(SERVER_SOFTWARE));
2258
2259          return Ok(Response::from_parts(response_parts, response_body));
2260        }
2261      };
2262    }
2263
2264    if log_enabled {
2265      log_combined(
2266        &logger,
2267        socket_data.remote_addr.ip(),
2268        latest_auth_data,
2269        log_method,
2270        log_request_path,
2271        log_protocol,
2272        response.status().as_u16(),
2273        match response.headers().get(header::CONTENT_LENGTH) {
2274          Some(header_value) => match header_value.to_str() {
2275            Ok(header_value) => match header_value.parse::<u64>() {
2276              Ok(content_length) => Some(content_length),
2277              Err(_) => response.body().size_hint().exact(),
2278            },
2279            Err(_) => response.body().size_hint().exact(),
2280          },
2281          None => response.body().size_hint().exact(),
2282        },
2283        log_referrer,
2284        log_user_agent,
2285      )
2286      .await;
2287    }
2288    Ok(response)
2289  }
2290}
2291
2292#[allow(clippy::too_many_arguments)]
2293pub async fn request_handler(
2294  request: Request<BoxBody<Bytes, std::io::Error>>,
2295  remote_address: SocketAddr,
2296  local_address: SocketAddr,
2297  encrypted: bool,
2298  config: Arc<Yaml>,
2299  logger: Sender<LogMessage>,
2300  handlers_vec: Vec<Box<dyn ServerModuleHandlers + Send>>,
2301  acme_http01_resolver_option: Option<Arc<ResolvesServerCertAcme>>,
2302  http3_alt_port: Option<u16>,
2303) -> Result<Response<BoxBody<Bytes, std::io::Error>>, anyhow::Error> {
2304  let timeout_yaml = &config["global"]["timeout"];
2305  if timeout_yaml.is_null() {
2306    request_handler_wrapped(
2307      request,
2308      remote_address,
2309      local_address,
2310      encrypted,
2311      config,
2312      logger,
2313      handlers_vec,
2314      acme_http01_resolver_option,
2315      http3_alt_port,
2316    )
2317    .await
2318    .map_err(|e| anyhow::anyhow!(e))
2319  } else {
2320    let timeout_millis = timeout_yaml.as_i64().unwrap_or(300000) as u64;
2321    match timeout(
2322      Duration::from_millis(timeout_millis),
2323      request_handler_wrapped(
2324        request,
2325        remote_address,
2326        local_address,
2327        encrypted,
2328        config,
2329        logger,
2330        handlers_vec,
2331        acme_http01_resolver_option,
2332        http3_alt_port,
2333      ),
2334    )
2335    .await
2336    {
2337      Ok(response) => response.map_err(|e| anyhow::anyhow!(e)),
2338      Err(_) => Err(anyhow::anyhow!("The client or server has timed out")),
2339    }
2340  }
2341}