ferron/util/
error_pages.rs

1use ferron_common::format_page;
2
3use super::anti_xss;
4
5/// Generates a default error page
6pub fn generate_default_error_page(status_code: hyper::StatusCode, server_administrator_email: Option<&str>) -> String {
7  let status_code_name = match status_code.canonical_reason() {
8    Some(reason) => format!("{} {}", status_code.as_u16(), reason),
9    None => format!("{}", status_code.as_u16()),
10  };
11
12  let error_500 = format!(
13    "The server encountered an unexpected error. \
14      You may need to contact the server administrator{} to resolve the error.",
15    match server_administrator_email {
16      Some(email_address) => format!(" at {email_address}"),
17      None => String::from(""),
18    }
19  );
20  let status_code_description = match status_code.as_u16() {
21    200 => "The request was successful!",
22    201 => "A new resource was successfully created.",
23    202 => "The request was accepted but hasn't been fully processed yet.",
24    400 => "The request was invalid.",
25    401 => "Authentication is required to access the resource.",
26    402 => "Payment is required to access the resource.",
27    403 => "You're not authorized to access this resource.",
28    404 => "The requested resource wasn't found. Double-check the URL if entered manually.",
29    405 => "The request method is not allowed for this resource.",
30    406 => "The server cannot provide a response in an acceptable format.",
31    407 => "Proxy authentication is required.",
32    408 => "The request took too long and timed out.",
33    409 => "There's a conflict with the current state of the server.",
34    410 => "The requested resource has been permanently removed.",
35    411 => "The request must include a Content-Length header.",
36    412 => "The request doesn't meet the server's preconditions.",
37    413 => "The request is too large for the server to process.",
38    414 => "The requested URL is too long.",
39    415 => "The server doesn't support the request's media type.",
40    416 => "The requested content range is invalid or unavailable.",
41    417 => "The expectation in the Expect header couldn't be met.",
42    418 => "This server (a teapot) refuses to make coffee! ☕",
43    421 => "The request was directed to the wrong server.",
44    422 => "The server couldn't process the provided content.",
45    423 => "The requested resource is locked.",
46    424 => "The request failed due to a dependency on another failed request.",
47    425 => "The server refuses to process a request that might be replayed.",
48    426 => "The client must upgrade its protocol to proceed.",
49    428 => "A precondition is required for this request, but it wasn't included.",
50    429 => "Too many requests were sent in a short period.",
51    431 => "The request headers are too large.",
52    451 => "Access to this resource is restricted due to legal reasons.",
53    497 => "A non-TLS request was sent to an HTTPS server.",
54    500 => &error_500,
55    501 => "The server doesn't support the requested functionality.",
56    502 => "The server, acting as a gateway, received an invalid response.",
57    503 => "The server is temporarily unavailable (e.g., maintenance or overload). Try again later.",
58    504 => "The server, acting as a gateway, timed out waiting for a response.",
59    505 => "The HTTP version used in the request isn't supported.",
60    506 => "The Variant header caused a content negotiation loop.",
61    507 => "The server lacks sufficient storage to complete the request.",
62    508 => "The server detected an infinite loop while processing the request.",
63    509 => "Bandwidth limit exceeded on the server.",
64    510 => "The server requires an extended HTTP request, but the client didn't send one.",
65    511 => "Authentication is required to access the network.",
66    598 => "The proxy server didn't receive a response in time.",
67    599 => "The proxy server couldn't establish a connection in time.",
68    _ => "No description found for the status code.",
69  };
70
71  format_page!(
72    format!(
73      "<main class=\"error-container\">
74      <h1>
75          <span class=\"error-code\">{}</span>
76          {}
77      </h1>
78      <p class=\"error-description\">{}</p>
79  </main>",
80      status_code.as_u16(),
81      status_code.canonical_reason().map_or("".to_string(), |r| format!(
82        "<span class=\"error-message\">{}</span>",
83        anti_xss(r)
84      )),
85      &anti_xss(status_code_description)
86    ),
87    &status_code_name,
88    vec![
89      include_str!("../../../assets/common.css"),
90      include_str!("../../../assets/error.css")
91    ]
92  )
93}