pub enum AppError {
Business {
code: i32,
msg: String,
},
LoginExpired {
msg: String,
},
DownloadUnAuth {
msg: String,
},
DownloadFailed {
msg: String,
},
Oss {
code: Option<i32>,
msg: String,
},
Database(String),
Internal(String),
}Expand description
应用层统一错误类型
封装所有业务异常,通过 [IntoResponse] 自动转换为 HTTP 响应。
§错误变体
| 变体 | HTTP 状态 | 响应格式 | 说明 |
|---|---|---|---|
Business | 200 | JSON {code, msg} | 业务逻辑错误 |
LoginExpired | 200 | JSON {code:401, msg} | Token 过期或未登录 |
DownloadUnAuth | 403 | 纯文本 | 下载权限不足 |
DownloadFailed | 500 | 纯文本 | 文件不存在或下载失败 |
Oss | 200 | JSON | OSS 对象存储异常 |
Database | 200 | JSON | 数据库查询/写入失败 |
Internal | 200 | JSON | 内部未知错误 |
§Panics
本类型不 panic。所有变体均通过 [IntoResponse] 优雅降级:
Database/Internal会将完整错误栈输出到tracing::error!日志Download*返回纯文本以避免浏览器 blob 下载保存 JSON- JSON 序列化失败时有 fallback 硬编码 JSON 字符串
§从 sqlx::Error 转换
ⓘ
// Repository 层可直接使用 ? 传播数据库错误
let row = sqlx::query("SELECT ...").fetch_one(&pool).await?;
// sqlx::Error 自动转为 AppError::DatabaseVariants§
Business
业务异常(带码)
LoginExpired
登录过期
DownloadUnAuth
下载无权限(返回纯文本 403)
DownloadFailed
下载失败(文件不存在等,返回纯文本 500,避免 blob 客户端保存 JSON)
Oss
OSS 异常
Database(String)
数据库错误
Internal(String)
内部错误
Implementations§
Source§impl AppError
impl AppError
Sourcepub fn business_code(code: i32, msg: impl Into<String>) -> Self
pub fn business_code(code: i32, msg: impl Into<String>) -> Self
Sourcepub fn login_expired(msg: impl Into<String>) -> Self
pub fn login_expired(msg: impl Into<String>) -> Self
Sourcepub fn download_unauth(msg: impl Into<String>) -> Self
pub fn download_unauth(msg: impl Into<String>) -> Self
Sourcepub fn download_failed(msg: impl Into<String>) -> Self
pub fn download_failed(msg: impl Into<String>) -> Self
构造下载失败错误(HTTP 500 纯文本)。
当 legacy 下载和 OSS 下载均不可用时调用。 返回纯文本以避免浏览器 blob 下载保存 JSON。
§返回值
返回 AppError::DownloadFailed 变体。
Trait Implementations§
Source§impl From<Error> for AppError
自动将 sqlx::Error 转换为 AppError::Database。
impl From<Error> for AppError
自动将 sqlx::Error 转换为 AppError::Database。
允许 Repository 层直接使用 ? 传播数据库错误:
ⓘ
let row = sqlx::query("SELECT ...").fetch_one(&pool).await?;Source§impl IntoResponse for AppError
将 AppError 转为 HTTP 响应。
impl IntoResponse for AppError
将 AppError 转为 HTTP 响应。
§转换规则
| 变体 | Content-Type | HTTP 状态 |
|---|---|---|
Business / LoginExpired / Oss | application/json;charset=UTF-8 | 200 |
DownloadUnAuth | text/plain | 403 |
DownloadFailed | text/plain | 500 |
Database / Internal | application/json;charset=UTF-8 | 200 |
§Errors
JSON 序列化失败时有硬编码 fallback,不会 panic。
Source§fn into_response(self) -> Response
fn into_response(self) -> Response
Create a response.
Auto Trait Implementations§
impl Freeze for AppError
impl RefUnwindSafe for AppError
impl Send for AppError
impl Sync for AppError
impl Unpin for AppError
impl UnsafeUnpin for AppError
impl UnwindSafe for AppError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
§impl<T, S> Handler<IntoResponseHandler, S> for T
impl<T, S> Handler<IntoResponseHandler, S> for T
§fn call(
self,
_req: Request<Body>,
_state: S,
) -> <T as Handler<IntoResponseHandler, S>>::Future
fn call( self, _req: Request<Body>, _state: S, ) -> <T as Handler<IntoResponseHandler, S>>::Future
Call the handler with the given request.
§fn layer<L>(self, layer: L) -> Layered<L, Self, T, S>where
L: Layer<HandlerService<Self, T, S>> + Clone,
<L as Layer<HandlerService<Self, T, S>>>::Service: Service<Request<Body>>,
fn layer<L>(self, layer: L) -> Layered<L, Self, T, S>where
L: Layer<HandlerService<Self, T, S>> + Clone,
<L as Layer<HandlerService<Self, T, S>>>::Service: Service<Request<Body>>,
Apply a [
tower::Layer] to the handler. Read more§fn with_state(self, state: S) -> HandlerService<Self, T, S>
fn with_state(self, state: S) -> HandlerService<Self, T, S>
Convert the handler into a [
Service] by providing the state§impl<H, T> HandlerWithoutStateExt<T> for Hwhere
H: Handler<T, ()>,
impl<H, T> HandlerWithoutStateExt<T> for Hwhere
H: Handler<T, ()>,
§fn into_service(self) -> HandlerService<H, T, ()>
fn into_service(self) -> HandlerService<H, T, ()>
Convert the handler into a [
Service] and no state.§fn into_make_service(self) -> IntoMakeService<HandlerService<H, T, ()>>
fn into_make_service(self) -> IntoMakeService<HandlerService<H, T, ()>>
Convert the handler into a
MakeService and no state. Read more§fn into_make_service_with_connect_info<C>(
self,
) -> IntoMakeServiceWithConnectInfo<HandlerService<H, T, ()>, C>
fn into_make_service_with_connect_info<C>( self, ) -> IntoMakeServiceWithConnectInfo<HandlerService<H, T, ()>, C>
Convert the handler into a
MakeService which stores information
about the incoming connection and has no state. Read more§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
Wrap the input message
T in a tonic::Request