Sign in

    #http_error —— 对外的错误契约

    HttpError / ErrorInfo / ErrorCode 与全部访问器。本包是纯契约:只定义错误长什么样;「什么情况下造错误」全在 client 包(造错误是编排层的行为),因此本包连传输层都不依赖。

    import { "q2316367743/moonhttp/http_error", }

    通常不必直接 import 本包:根包 @moonhttp 已把三个类型再导出。

    #HttpError

    方法说明
    code()错误分类(ErrorCode)
    message()面向人的错误描述
    config()触发错误的配置(已完成合并),便于定位是哪一项配置不对
    response()已经收到的响应:状态码校验失败时是完整响应;传输层失败发生在响应头之后时是失败前的部分(响应体可能只有半截);连响应头都没收到时 None
    is_cancelled()是否被取消信号叫停(对应 axios 的 axios.isCancel)
    new(message, code, config)不带响应地造一个错误——给请求拦截器主动中止请求用

    #解构的写法

    pub using 能再导出类型,但再导出不了构造器,所以构造器模式要写类型限定的形式:

    try {
    ignore(api.request(config))
    } catch {
    @moonhttp.HttpError::HttpError(info) => {
    println(info.code)
    println(info.message)
    }
    }

    不想解构时用访问器更顺手:catch { error => error.code() }。

    #ErrorCode

    BadRequest(4xx)/ BadResponse(5xx 及被拒状态码)/ Network / Timeout / InvalidUrl / NotSupported / Cancelled / TooManyRedirects。to_string() 渲染成 axios 风格错误码字符串(ERR_BAD_REQUEST、ECONNABORTED、ERR_CANCELED 等),Show 实现与它一致。

    错误契约的完整说明见 docs/04-errors.md。

    HttpError

    pub(all) suberror HttpError {
    HttpError(ErrorInfo)
    }

    本模块对外的错误类型。

    用 pub(all) suberror 而不是 pub suberror:后者不导出构造子, 使用方就只能拿到错误、无法按分类匹配。这里刻意把构造子放开, 让调用方能写 catch { @moonhttp.HttpError::HttpError(info) => ... } ——构造器不做包限定裸写不出来(pub using 再导出不了构造器, 实测证据见 docs/01-architecture.md),类型限定的写法不受影响。

    同理,client 包的抛错点也靠 pub(all) 跨包构造本类型。
    impl Show for HttpError

    HttpError::code

    fn HttpError::code(self : HttpError) -> ErrorCode

    错误的分类。

    HttpError::config

    触发这次错误的配置(已完成合并)。

    HttpError::info

    fn HttpError::info(self : HttpError) -> ErrorInfo

    取出错误的详细信息。

    HttpError::is_cancelled

    fn HttpError::is_cancelled(self : HttpError) -> Bool

    这次失败是不是被取消(对应 axios 的 axios.isCancel)。

    等价于 error.code() is ErrorCode::Cancelled,存在的意义是让调用点读起来 与 axios 的写法一致,也避免每次手写模式匹配。取消来自调用方自己的 AbortController(不是超时、不是网络错误),通常该安静地收场而不是报错。

    client.request(config) catch {
    error if error.is_cancelled() => println("已取消:" + error.message())
    error => println(error.to_string())
    }

    HttpError::message

    fn HttpError::message(self : HttpError) -> String

    错误的文字描述。

    HttpError::new

    fn HttpError::new(message : String, code : ErrorCode, config :
    Config
    ) -> HttpError

    直接构造一个不带响应的 HttpError。

    这是 ErrorInfo 的公开入口:包外的代码此前只能读错误、不能造错误,而 请求拦截器需要造——它主动中止请求时就得抛一个错误出去,见 docs/11-interceptors.md:

    .use_request(config => {
    if token == "" {
    raise @moonhttp.HttpError::new("缺少 token", @moonhttp.ErrorCode::BadRequest, config)
    }
    config.with_header("Authorization", token)
    })

    code 由调用方按语义选。客户端侧拒绝请求(缺凭据、参数不合法)建议用 ErrorCode::BadRequest:axios 在同样的位置上用的也是 ERR_BAD_REQUEST (它同时覆盖「4xx 响应」与「请求本身不合法」两种情况)。

    错误里没有响应(response() 返回 None):这次请求根本没发出去。 要把某个响应挂上去,用 ErrorInfo 字面量自己造。

    HttpError::output

    fn HttpError::output(self : HttpError, logger : &Logger) -> Unit

    HttpError::response

    错误里带的响应:

    • 状态码没通过校验时是完整响应;
    • 传输层失败(超时、断连)发生在响应头到手之后时,是失败前已经收到的部分 ——响应体字节可能只有半截(bytes() / text() 拿到的就是那半截);
    • 连响应头都没收到时为 None。

    HttpError::to_string

    fn HttpError::to_string(self : HttpError) -> String

    渲染成 错误码: 描述 的形式,便于日志与断言。

    ErrorCode

    pub(all) enum ErrorCode {
    BadRequest
    BadResponse
    Network
    Timeout
    InvalidUrl
    NotSupported
    Cancelled
    TooManyRedirects
    } derive(Eq,
    Debug
    )

    错误的分类,对应 axios 的 AxiosError.code。

    分成这几档是为了让调用方能按「该怎么处理」分支: 超时可以重试,网络失败要看连接,4xx 要看自己的请求参数, 5xx 要等服务端恢复。
    impl Show for ErrorCode

    ErrorCode::equal

    fn ErrorCode::equal(ErrorCode, ErrorCode) -> Bool

    ErrorCode::not_equal

    fn ErrorCode::not_equal(x : ErrorCode, y : ErrorCode) -> Bool

    ErrorCode::output

    fn ErrorCode::output(self : ErrorCode, logger : &Logger) -> Unit

    ErrorCode::to_string

    fn ErrorCode::to_string(self : ErrorCode) -> String

    渲染成 axios 风格的错误码字符串(即 AxiosError.code 的取值)。

    超时用的是 ECONNABORTED 而不是 ETIMEDOUT:axios 默认就是前者, 只有在打开 transitional.clarifyTimeoutError 时才会改用后者。

    取消用的是 ERR_CANCELED(axios 的 AxiosError.ERR_CANCELED,也是 它 CanceledError 上的 code);与超时分开,调用方才能把「用户主动中止」 与「超时兜底」区分对待——前者通常不该重试,也不该报给用户。

    重定向上限用 ERR_FR_TOO_MANY_REDIRECTS:这是 axios 透传的 follow-redirects 错误码(axios 自己也定义了 AxiosError.ERR_FR_TOO_MANY_REDIRECTS 这个常量),跟着用同一个字符串,调用方按码分支时不必区分是哪一家的实现。

    ErrorInfo

    pub(all) struct ErrorInfo {
    message : String
    code : ErrorCode
    config :
    Config

    response :
    Response
    ?
    }

    错误的详细信息,对应 AxiosError 上的 message / code / config / response。

    Source Files