improve user-facing error handling
This commit is contained in:
parent
4e96f3989c
commit
faed4ceb30
3 changed files with 39 additions and 17 deletions
|
|
@ -11,8 +11,9 @@ pub enum StatusCode {
|
|||
OK,
|
||||
BadRequest,
|
||||
NotFound,
|
||||
ImATeapot,
|
||||
InternalServerError,
|
||||
// ImATeapot,
|
||||
BadGateway,
|
||||
}
|
||||
|
||||
impl StatusCode {
|
||||
|
|
@ -21,8 +22,9 @@ impl StatusCode {
|
|||
StatusCode::OK => 200,
|
||||
StatusCode::BadRequest => 400,
|
||||
StatusCode::NotFound => 404,
|
||||
// StatusCode::ImATeapot => 418,
|
||||
StatusCode::ImATeapot => 418,
|
||||
StatusCode::InternalServerError => 500,
|
||||
StatusCode::BadGateway => 502,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
40
src/main.rs
40
src/main.rs
|
|
@ -53,6 +53,23 @@ fn parse_address(address: &str) -> Result<SocketAddr> {
|
|||
}
|
||||
}
|
||||
|
||||
fn query_error_to_user_response(err: &Error, query_address: &String, address: &SocketAddr) -> (StatusCode, String) {
|
||||
match err.kind() {
|
||||
ErrorKind::HostUnreachable =>
|
||||
(StatusCode::BadGateway, format!(
|
||||
"Host unreachable: {} ({})\n",
|
||||
query_address, address)),
|
||||
ErrorKind::InvalidData =>
|
||||
(StatusCode::BadGateway, format!(
|
||||
"Server returned invalid data: {} ({})\n",
|
||||
query_address, address)),
|
||||
_ =>
|
||||
(StatusCode::InternalServerError, format!(
|
||||
"Failed to connect: {} ({}).\n",
|
||||
query_address, address)),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_html_request(request: &Request, response: &mut Response, verbose: bool) -> Result<StatusCode> {
|
||||
let content = include_str!("views/index.html");
|
||||
response.set_header("Content-Type", "text/html".to_string());
|
||||
|
|
@ -75,19 +92,16 @@ fn handle_html_request(request: &Request, response: &mut Response, verbose: bool
|
|||
match MinecraftStatus::fetch(&address, verbose) {
|
||||
Err(err) => {
|
||||
println!(
|
||||
"Failed to connect to {} ({}): {}",
|
||||
"Failed to query {} ({}): {}",
|
||||
query_address, address, err);
|
||||
|
||||
response.body(format!(
|
||||
"Failed to connect to {} ({}).\n",
|
||||
query_address, address));
|
||||
response.status(StatusCode::InternalServerError);
|
||||
let (code, msg) = query_error_to_user_response(&err, query_address, &address);
|
||||
|
||||
response.status(code);
|
||||
query_response = format!(
|
||||
"<hr/>
|
||||
<h2>Server Details</h2>
|
||||
<pre><code>Failed to connect to {} ({}).</pre></code>",
|
||||
sanitize_html(query_address),
|
||||
sanitize_html(&address.to_string()),
|
||||
<pre><code>{msg}</pre></code>",
|
||||
);
|
||||
}
|
||||
Ok(status) => {
|
||||
|
|
@ -155,10 +169,10 @@ fn handle_json_request(request: &Request, response: &mut Response, verbose: bool
|
|||
"Failed to connect to {} ({}): {}",
|
||||
query_address, address, err);
|
||||
|
||||
response.status(StatusCode::InternalServerError);
|
||||
response.body(format!(
|
||||
"Failed to connect to {} ({}).\n",
|
||||
query_address, address));
|
||||
let (code, msg) = query_error_to_user_response(&err, query_address, &address);
|
||||
|
||||
response.status(code);
|
||||
response.body(msg);
|
||||
}
|
||||
Ok(status) => {
|
||||
let minecraft_status = MinecraftStatusResponse{
|
||||
|
|
@ -241,7 +255,7 @@ fn main() -> Result<()> {
|
|||
Err (e) => {
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to fetch status: {}", e)));
|
||||
format!("Failed to query server: {}", e)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,10 +128,16 @@ impl MinecraftStatus {
|
|||
}
|
||||
}
|
||||
|
||||
let data = std::str::from_utf8(&data[offset..]).expect("Failed to parse UTF-8 data");
|
||||
let data = match std::str::from_utf8(&data[offset..]) {
|
||||
Ok(data) => data,
|
||||
Err(err) => return Err(Error::new(ErrorKind::InvalidData, format!("Failed to parse UTF-8 data: {err}")))
|
||||
};
|
||||
let sanitised: String = data.chars().filter(
|
||||
|&c| c >= '\u{20}' || c == '\n' || c == '\r' || c == '\t').collect();
|
||||
let status: MinecraftStatus = serde_json::from_str(&sanitised).expect("Failed to parse JSON");
|
||||
let status: MinecraftStatus = match serde_json::from_str(&sanitised) {
|
||||
Ok(status) => status,
|
||||
Err(err) => return Err(Error::new(ErrorKind::InvalidData, format!("Failed to parse JSON: {err}"))),
|
||||
};
|
||||
|
||||
Ok(status)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue