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