Rust错误处理库tor-error的使用:高效管理与自定义Tor网络错误类型

Rust错误处理库tor-error的使用:高效管理与自定义Tor网络错误类型

tor-error简介

tor-error是用于Tor和Arti项目中的错误处理支持库。它主要提供以下功能:

  1. ErrorKind枚举类型
  2. 关联的HasKind trait
  3. 其他一些支持上层依赖栈错误处理的辅助功能

特性

  • backtrace:在内部错误中启用回溯(默认启用)

实验性特性

这些API不包含在语义版本控制保证中,可能会在补丁版本间破坏或移除:

  • experimental-api:向公共接口添加额外的非稳定API

许可证

MIT OR Apache-2.0

安装

在项目目录中运行以下Cargo命令:

cargo add tor-error

或者在Cargo.toml中添加:

tor-error = "0.32.0"

完整示例代码

以下是一个扩展的使用tor-error的完整示例,展示更复杂的Tor网络错误处理:

use tor_error::{ErrorKind, HasKind};
use std::error::Error;
use std::fmt;

// 自定义Tor网络错误类型
#[derive(Debug)]
struct TorNetworkError {
    kind: ErrorKind,
    message: String,
    source: Option<Box<dyn Error>>, // 错误来源
}

impl TorNetworkError {
    // 创建新错误
    fn new(kind: ErrorKind, message: &str) -> Self {
        TorNetworkError {
            kind,
            message: message.to_string(),
            source: None,
        }
    }

    // 创建带源错误的错误
    fn with_source(kind: ErrorKind, message: &str, source: Box<dyn Error>) -> Self {
        TorNetworkError {
            kind,
            message: message.to_string(),
            source: Some(source),
        }
    }

    // 获取错误严重性
    fn severity(&self) -> &str {
        match self.kind {
            ErrorKind::Internal => "Critical",
            ErrorKind::TorProtocolViolation => "High",
            _ => "Medium",
        }
    }
}

impl fmt::Display for TorNetworkError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "[{:?}] Tor Error: {}", self.kind, self.message)?;
        if let Some(source) = &self.source {
            write!(f, " (Source: {})", source)?;
        }
        Ok(())
    }
}

impl Error for TorNetworkError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        self.source.as_deref()
    }
}

impl HasKind for TorNetworkError {
    fn kind(&self) -> ErrorKind {
        self.kind
    }
}

// 模拟底层IO错误
#[derive(Debug)]
struct IoError {
    details: String,
}

impl fmt::Display for IoError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "IO Error: {}", self.details)
    }
}

impl Error for IoError {}

fn simulate_network_operation() -> Result<(), Box<dyn Error>> {
    // 模拟底层IO错误
    let io_err = IoError {
        details: "Connection timed out".to_string(),
    };
    
    // 将IO错误包装为Tor网络错误
    Err(Box::new(TorNetworkError::with_source(
        ErrorKind::Internal,
        "Failed to read from network socket",
        Box::new(io_err),
    )))
}

fn main() -> Result<(), Box<dyn Error>> {
    match simulate_network_operation() {
        Ok(_) => println!("Operation succeeded"),
        Err(e) => {
            // 处理错误
            if let Some(tor_err) = e.downcast_ref::<TorNetworkError>() {
                println!("Tor Network Error occurred:");
                println!("Error: {}", tor_err);
                println!("Kind: {:?}", tor_err.kind());
                println!("Severity: {}", tor_err.severity());
                
                if let Some(source) = tor_err.source() {
                    println!("Caused by: {}", source);
                }
                
                // 根据错误类型采取不同措施
                match tor_err.kind() {
                    ErrorKind::Internal => {
                        println!("Critical error - terminating connection");
                    }
                    ErrorKind::TorProtocolViolation => {
                        println!("Protocol violation - logging and continuing");
                    }
                    _ => {
                        println!("Other error - retrying operation");
                    }
                }
            } else {
                println!("Unknown error: {}", e);
            }
        }
    }
    
    Ok(())
}

这个扩展示例展示了:

  1. 更复杂的自定义Tor网络错误类型,包含错误来源
  2. 错误严重性分级
  3. 错误链的包装和处理
  4. 使用downcast_ref进行错误类型检查
  5. 完整的错误处理流程

您可以根据实际需求进一步扩展,例如添加更多的错误种类或自定义错误处理方法。


1 回复

Rust错误处理库tor-error的使用:高效管理与自定义Tor网络错误类型

tor-error是Tor项目中的一个错误处理库,专门用于处理Tor网络相关的错误情况。它提供了一套结构化的错误类型和实用工具,帮助开发者高效管理Tor网络应用中的错误。

主要特性

  1. 为Tor网络操作提供标准化的错误类型
  2. 支持错误链(Error chaining)和上下文信息
  3. 提供便捷的错误构建和转换方法
  4. 支持自定义错误类型扩展

基本使用方法

添加依赖

首先在Cargo.toml中添加依赖:

[dependencies]
tor-error = "0.4"

基本错误处理

use tor_error::{ErrorKind, HasKind};

fn connect_to_tor() -> Result<(), tor_error::Error> {
    // 模拟一个错误
    Err(tor_error::Error::new(
        ErrorKind::TorNetworkUnreachable,
        "Failed to connect to Tor network"
    ))
}

fn main() {
    match connect_to_tor() {
        Ok(_) => println!("Connected successfully"),
        Err(e) => {
            println!("Error: {}", e);
            println!("Error kind: {:?}", e.kind());
        }
    }
}

自定义错误类型

use tor_error::{ErrorKind, HasKind, Error};

#[derive(Debug, Clone)]
enum MyCustomError {
    CircuitFailure,
    AuthenticationFailed,
}

impl std::fmt::Display for MyCustomError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            MyCustomError::CircuitFailure => write!(f, "Tor circuit failed"),
            MyCustomError::AuthenticationFailed => write(f, "Authentication failed"),
        }
    }
}

impl std::error::Error for MyCustomError {}

impl HasKind for MyCustomError {
    fn kind(&self) -> ErrorKind {
        match self {
            MyCustomError::CircuitFailure => ErrorKind::TorProtocolViolation,
            MyCustomError::AuthenticationFailed => ErrorKind::TorAccessFailed,
        }
    }
}

fn custom_operation() -> Result<(), Error> {
    // 模拟返回自定义错误
    let custom_err = MyCustomError::CircuitFailure;
    Err(Error::from(custom_err))
}

错误链和上下文

use tor-error::{Error, ErrorKind};

fn connect_to_relay() -> Result<(), Error> {
    // 模拟一个底层IO错误
    let io_err = std::io::Error::new(
        std::io::ErrorKind::ConnectionRefused,
        "Connection refused by relay"
    );
    
    // 添加上下文信息并转换为tor-error
    Err(Error::from(io_err)
        .with_source(ErrorKind::TorNetworkUnreachable)
        .context("Failed to connect to Tor relay"))
}

fn main() {
    if let Err(e) = connect_to_relay() {
        println!("Error: {}", e);
        println!("Full error chain:");
        for cause in e.chain() {
            println!("- {}", cause);
        }
    }
}

错误种类(ErrorKind)

tor-error定义了一些常见的Tor网络错误种类:

pub enum ErrorKind {
    /// 内部错误
    Internal,
    /// Tor协议违规
    TorProtocolViolation,
    /// 网络不可达
    TorNetworkUnreachable,
    /// 访问被拒绝
    TorAccessFailed,
    /// 配置错误
    TorConfigError,
    /// 超时
    TorTimeout,
    /// 资源耗尽
    TorResourceExhausted,
    // ... 其他种类
}

高级用法

错误包装和转换

use tor_error::{Error, ErrorKind};

fn parse_tor_response(response: &str) -> Result<(), Error> {
    // 假设解析失败
    let parse_err = "Invalid Tor response format".to_string();
    
    // 将字符串错误转换为tor-error
    Err(Error::new(ErrorKind::TorProtocolViolation, parse_err))
}

fn handle_response() -> Result<(), Error> {
    let response = "BAD_RESPONSE";
    parse_tor_response(response).map_err(|e| {
        // 添加上下文信息
        e.context("Failed to process Tor server response")
    })?;
    Ok(())
}

批量错误处理

use tor-error::{Error, ErrorKind};

fn check_multiple_relays() -> Result<(), Vec<Error>> {
    let mut errors = Vec::new();
    
    for relay in &["relay1", "relay2", "relay3"] {
        if let Err(e) = check_relay(relay) {
            errors.push(e);
        }
    }
    
    if errors.is_empty() {
        Ok(())
    } else {
        Err(errors)
    }
}

fn check_relay(relay: &str) -> Result<(), Error> {
    // 模拟检查失败
    Err(Error::new(
        ErrorKind::TorNetworkUnreachable,
        format!("Relay {} unavailable", relay)
    ))
}

完整示例代码

下面是一个综合使用tor-error的完整示例,展示了从基本错误处理到自定义错误类型的完整流程:

use tor_error::{Error, ErrorKind, HasKind};
use std::error::Error as StdError;

// 自定义错误类型
#[derive(Debug)]
enum TorAppError {
    ConnectionFailed,
    InvalidResponse,
    AuthenticationError,
}

impl std::fmt::Display for TorAppError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            TorAppError::ConnectionFailed => write!(f, "Tor connection failed"),
            TorAppError::InvalidResponse => write!(f, "Invalid response from Tor network"),
            TorAppError::AuthenticationError => write!(f, "Authentication failed"),
        }
    }
}

impl StdError for TorAppError {}

impl HasKind for TorAppError {
    fn kind(&self) -> ErrorKind {
        match self {
            TorAppError::ConnectionFailed => ErrorKind::TorNetworkUnreachable,
            TorAppError::InvalidResponse => ErrorKind::TorProtocolViolation,
            TorAppError::AuthenticationError => ErrorKind::TorAccessFailed,
        }
    }
}

// 模拟Tor连接函数
fn connect_to_tor() -> Result<(), Error> {
    // 这里模拟一个底层IO错误
    let io_error = std::io::Error::new(
        std::io::ErrorKind::ConnectionRefused,
        "Connection refused by Tor node"
    );
    
    // 转换为tor-error并添加上下文
    Err(Error::from(io_error)
        .with_source(ErrorKind::TorNetworkUnreachable)
        .context("Failed to establish Tor connection"))
}

// 模拟处理Tor响应
fn process_tor_response(response: &str) -> Result<(), Error> {
    if response.is_empty() {
        // 使用自定义错误类型
        let custom_error = TorAppError::InvalidResponse;
        return Err(Error::from(custom_error)
            .context("Empty response received"));
    }
    
    // 模拟处理逻辑
    if response == "AUTH_FAILED" {
        let auth_error = TorAppError::AuthenticationError;
        return Err(Error::from(auth_error));
    }
    
    Ok(())
}

fn main() {
    // 示例1: 处理连接错误
    match connect_to_tor() {
        Ok(_) => println!("Connected to Tor successfully"),
        Err(e) => {
            println!("Connection Error: {}", e);
            println!("Error kind: {:?}", e.kind());
            println!("Error chain:");
            for cause in e.chain() {
                println!("- {}", cause);
            }
        }
    }

    // 示例2: 处理响应错误
    let responses = ["GOOD", "", "AUTH_FAILED"];
    for response in responses.iter() {
        println!("\nProcessing response: {}", response);
        match process_tor_response(response) {
            Ok(_) => println!("Response processed successfully"),
            Err(e) => {
                println!("Error processing response: {}", e);
                println!("Error kind: {:?}", e.kind());
            }
        }
    }

    // 示例3: 批量错误处理
    let mut all_errors = Vec::new();
    for node in &["node1", "node2", "node3"] {
        if let Err(e) = check_node_availability(node) {
            all_errors.push(e);
        }
    }
    
    if !all_errors.is_empty() {
        println!("\nBatch errors:");
        for err in all_errors {
            println!("- {}", err);
        }
    }
}

fn check_node_availability(node: &str) -> Result<(), Error> {
    // 模拟节点检查
    if node == "node2" {
        Err(Error::new(
            ErrorKind::TorNetworkUnreachable,
            format!("Node {} is unreachable", node)
        ))
    } else {
        Ok(())
    }
}

最佳实践

  1. 尽可能使用tor-error提供的错误类型而不是基础错误类型
  2. 为自定义错误实现HasKind trait以保持一致性
  3. 使用context()方法添加上下文信息
  4. 利用错误链来保留完整的错误信息
  5. 根据错误种类(ErrorKind)实现不同的恢复逻辑

tor-error为Tor网络应用提供了强大而灵活的错误处理能力,通过结构化的错误类型和丰富的工具方法,可以显著提高错误处理代码的可读性和可维护性。

回到顶部