// ============================================================================
// 三条链的驱动:顺序与错误流转。全部是包私有函数,
// 只被 `pipeline.mbt` 的 `Client::request`(与 `stream_entry.mbt` 的
// 请求侧正常链)调用。
// ============================================================================
///|
/// 跑请求侧正常链:**后注册先跑**(LIFO,与 axios 一致),每个拦截器拿到的都是
/// 上一个(更晚注册的)拦截器交出来的配置。
///
/// 不抛错而是返回 `Result`:被拦下不是本函数的异常,而是「这次请求不发了」,
/// 按来源分流应当交给请求侧的错误处理器——交给谁由调用方决定(`request` 交给
/// `run_request_errors`,两个流式入口没有错误处理器,直接抛)。
/// 因此这里显式标 `noraise`:拦截器抛出的错误全部收进了 `Err`,调用方不必
/// (也不该)在自己的错误类型里为它留位置。
async fn Interceptors::run_request(
self : Interceptors,
config : Config,
) -> Result[Config, HttpError] noraise {
let mut outcome : Result[Config, HttpError] = Ok(config)
for i = self.requests.length() - 1; i >= 0; i = i - 1 {
// 字段里的函数值要先绑到局部变量再调:`pair.on_fulfilled(x)` 会被当成
// 「在 `RequestPair` 上找一个叫 on_fulfilled 的方法」。
let on_request = self.requests[i].on_fulfilled
outcome = match outcome {
// 正常路径:交出配置;拦截器抛错就转成「已拦下」。
Ok(current) => Ok(on_request(current)) catch { error => Err(error) }
// 已经被拦下:正常处理器全部跳过,错误留给错误链。
Err(error) => Err(error)
}
}
outcome
}
///|
/// 跑请求侧错误链:**后注册先跑**(与请求侧正常链同向,理由见
/// `docs/11-interceptors.md`)。
///
/// 每个错误处理器拿到当前错误:返回 `Response` 表示就地救回,立刻结束(这次请求
/// 的结果就是它);`raise error` 表示不处理,把(可能是自己新造的)错误交给更早
/// 注册的处理器。全部没接住就抛最后那个错误——与 axios 的 promise 链一样,
/// 错误处理器可以「换一个错误继续往外传」。
async fn Interceptors::run_request_errors(
self : Interceptors,
error : HttpError,
) -> Response raise HttpError {
let mut current = error
let mut rescued : Response? = None
for i = self.requests.length() - 1; i >= 0; i = i - 1 {
// 救回来之后剩下的处理器不再打扰:链的意义就是「谁接住就谁说了算」。
if rescued is None {
let on_rejected = self.requests[i].on_rejected
let outcome = Ok(on_rejected(current)) catch { e => Err(e) }
match outcome {
Ok(response) => rescued = Some(response)
Err(next) => current = next
}
}
}
match rescued {
Some(response) => response
None => raise current
}
}
///|
/// 跑响应侧链:**先注册先跑**(FIFO,与 axios 一致)。
///
/// 进来的 `outcome` 只有两种来源:通过校验的响应,或**状态码没通过校验**的错误
/// (请求阶段的失败不进这里,它们走 `run_request_errors`)。与 axios 的 promise
/// 链同构:`Ok` 走正常处理器、`Err` 走错误处理器;处理器自己抛出的错误落到
/// **更晚注册**的错误处理器手里,没人接住就抛给调用方。
/// 所以「状态码失败的重试」写在哪里是有讲究的:越早注册的错误处理器越先看到错误。
async fn Interceptors::run_response(
self : Interceptors,
outcome : Result[Response, HttpError],
) -> Response raise HttpError {
let mut state = outcome
for pair in self.responses {
let on_fulfilled = pair.on_fulfilled
let on_rejected = pair.on_rejected
state = match state {
Ok(response) => Ok(on_fulfilled(response)) catch { error => Err(error) }
Err(error) => Ok(on_rejected(error)) catch { error => Err(error) }
}
}
match state {
Ok(response) => response
Err(error) => raise error
}
}