refactor: improve error handle (#195)

This commit is contained in:
sigoden 2023-03-12 15:20:40 +08:00 committed by GitHub
parent c92e45f2da
commit 29a04c8d74
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 17 additions and 25 deletions

View file

@ -1,4 +1,4 @@
use anyhow::{anyhow, bail, Result}; use anyhow::{bail, Context, Result};
use clap::builder::PossibleValuesParser; use clap::builder::PossibleValuesParser;
use clap::{value_parser, Arg, ArgAction, ArgMatches, Command}; use clap::{value_parser, Arg, ArgAction, ArgMatches, Command};
use clap_complete::{generate, Generator, Shell}; use clap_complete::{generate, Generator, Shell};
@ -380,7 +380,7 @@ impl Args {
p.push(path); // If path is absolute, it replaces the current path. p.push(path); // If path is absolute, it replaces the current path.
std::fs::canonicalize(p) std::fs::canonicalize(p)
}) })
.map_err(|err| anyhow!("Failed to access path `{}`: {}", path.display(), err,)) .with_context(|| format!("Failed to access path `{}`", path.display()))
} }
fn parse_assets_path<P: AsRef<Path>>(path: P) -> Result<PathBuf> { fn parse_assets_path<P: AsRef<Path>>(path: P) -> Result<PathBuf> {

View file

@ -18,7 +18,7 @@ use crate::server::{Request, Server};
#[cfg(feature = "tls")] #[cfg(feature = "tls")]
use crate::tls::{TlsAcceptor, TlsStream}; use crate::tls::{TlsAcceptor, TlsStream};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Context, Result};
use std::net::{IpAddr, SocketAddr, TcpListener as StdTcpListener}; use std::net::{IpAddr, SocketAddr, TcpListener as StdTcpListener};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc; use std::sync::Arc;
@ -35,14 +35,7 @@ use hyper::service::{make_service_fn, service_fn};
use rustls::ServerConfig; use rustls::ServerConfig;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() -> Result<()> {
run().await.unwrap_or_else(|err| {
eprintln!("error: {err}");
std::process::exit(1);
})
}
async fn run() -> Result<()> {
logger::init().map_err(|e| anyhow!("Failed to init logger, {e}"))?; logger::init().map_err(|e| anyhow!("Failed to init logger, {e}"))?;
let cmd = build_cli(); let cmd = build_cli();
let matches = cmd.get_matches(); let matches = cmd.get_matches();
@ -94,7 +87,7 @@ fn serve(
match bind_addr { match bind_addr {
BindAddr::Address(ip) => { BindAddr::Address(ip) => {
let incoming = create_addr_incoming(SocketAddr::new(*ip, port)) let incoming = create_addr_incoming(SocketAddr::new(*ip, port))
.map_err(|e| anyhow!("Failed to bind `{ip}:{port}`, {e}"))?; .with_context(|| format!("Failed to bind `{ip}:{port}`"))?;
match args.tls.as_ref() { match args.tls.as_ref() {
#[cfg(feature = "tls")] #[cfg(feature = "tls")]
Some((certs, key)) => { Some((certs, key)) => {
@ -134,7 +127,7 @@ fn serve(
#[cfg(unix)] #[cfg(unix)]
{ {
let listener = tokio::net::UnixListener::bind(path) let listener = tokio::net::UnixListener::bind(path)
.map_err(|e| anyhow!("Failed to bind `{}`, {e}", path.display()))?; .with_context(|| format!("Failed to bind `{}`", path.display()))?;
let acceptor = unix::UnixAcceptor::from_listener(listener); let acceptor = unix::UnixAcceptor::from_listener(listener);
let new_service = make_service_fn(move |_| serve_func(None)); let new_service = make_service_fn(move |_| serve_func(None));
let server = tokio::spawn(hyper::Server::builder(acceptor).serve(new_service)); let server = tokio::spawn(hyper::Server::builder(acceptor).serve(new_service));
@ -181,8 +174,8 @@ fn print_listening(args: Arc<Args>) -> Result<()> {
} }
} }
if ipv4 || ipv6 { if ipv4 || ipv6 {
let ifaces = if_addrs::get_if_addrs() let ifaces =
.map_err(|e| anyhow!("Failed to get local interface addresses: {e}"))?; if_addrs::get_if_addrs().with_context(|| "Failed to get local interface addresses")?;
for iface in ifaces.into_iter() { for iface in ifaces.into_iter() {
let local_ip = iface.ip(); let local_ip = iface.ip();
if ipv4 && local_ip.is_ipv4() { if ipv4 && local_ip.is_ipv4() {

View file

@ -1,4 +1,4 @@
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Context as AnyhowContext, Result};
use core::task::{Context, Poll}; use core::task::{Context, Poll};
use futures::ready; use futures::ready;
use hyper::server::accept::Accept; use hyper::server::accept::Accept;
@ -128,12 +128,11 @@ impl Accept for TlsAcceptor {
pub fn load_certs<T: AsRef<Path>>(filename: T) -> Result<Vec<Certificate>> { pub fn load_certs<T: AsRef<Path>>(filename: T) -> Result<Vec<Certificate>> {
// Open certificate file. // Open certificate file.
let cert_file = fs::File::open(filename.as_ref()) let cert_file = fs::File::open(filename.as_ref())
.map_err(|e| anyhow!("Failed to access `{}`, {e}", filename.as_ref().display()))?; .with_context(|| format!("Failed to access `{}`", filename.as_ref().display()))?;
let mut reader = io::BufReader::new(cert_file); let mut reader = io::BufReader::new(cert_file);
// Load and return certificate. // Load and return certificate.
let certs = let certs = rustls_pemfile::certs(&mut reader).with_context(|| "Failed to load certificate")?;
rustls_pemfile::certs(&mut reader).map_err(|_| anyhow!("Failed to load certificate"))?;
if certs.is_empty() { if certs.is_empty() {
bail!("No supported certificate in file"); bail!("No supported certificate in file");
} }
@ -143,12 +142,12 @@ pub fn load_certs<T: AsRef<Path>>(filename: T) -> Result<Vec<Certificate>> {
// Load private key from file. // Load private key from file.
pub fn load_private_key<T: AsRef<Path>>(filename: T) -> Result<PrivateKey> { pub fn load_private_key<T: AsRef<Path>>(filename: T) -> Result<PrivateKey> {
let key_file = fs::File::open(filename.as_ref()) let key_file = fs::File::open(filename.as_ref())
.map_err(|e| anyhow!("Failed to access `{}`, {e}", filename.as_ref().display()))?; .with_context(|| format!("Failed to access `{}`", filename.as_ref().display()))?;
let mut reader = io::BufReader::new(key_file); let mut reader = io::BufReader::new(key_file);
// Load and return a single private key. // Load and return a single private key.
let keys = rustls_pemfile::read_all(&mut reader) let keys = rustls_pemfile::read_all(&mut reader)
.map_err(|e| anyhow!("There was a problem with reading private key: {e}"))? .with_context(|| "There was a problem with reading private key")?
.into_iter() .into_iter()
.find_map(|item| match item { .find_map(|item| match item {
rustls_pemfile::Item::RSAKey(key) rustls_pemfile::Item::RSAKey(key)

View file

@ -1,4 +1,4 @@
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Context, Result};
use std::{ use std::{
borrow::Cow, borrow::Cow,
path::Path, path::Path,
@ -8,7 +8,7 @@ use std::{
pub fn unix_now() -> Result<Duration> { pub fn unix_now() -> Result<Duration> {
SystemTime::now() SystemTime::now()
.duration_since(UNIX_EPOCH) .duration_since(UNIX_EPOCH)
.map_err(|err| anyhow!("Invalid system time, {err}")) .with_context(|| "Invalid system time")
} }
pub fn encode_uri(v: &str) -> String { pub fn encode_uri(v: &str) -> String {

View file

@ -37,7 +37,7 @@ fn wrong_path_cert() -> Result<(), Error> {
.args(["--tls-cert", "wrong", "--tls-key", "tests/data/key.pem"]) .args(["--tls-cert", "wrong", "--tls-key", "tests/data/key.pem"])
.assert() .assert()
.failure() .failure()
.stderr(contains("error: Failed to access `wrong`")); .stderr(contains("Failed to access `wrong`"));
Ok(()) Ok(())
} }
@ -49,7 +49,7 @@ fn wrong_path_key() -> Result<(), Error> {
.args(["--tls-cert", "tests/data/cert.pem", "--tls-key", "wrong"]) .args(["--tls-cert", "tests/data/cert.pem", "--tls-key", "wrong"])
.assert() .assert()
.failure() .failure()
.stderr(contains("error: Failed to access `wrong`")); .stderr(contains("Failed to access `wrong`"));
Ok(()) Ok(())
} }