Skip to content

Commit 96638e3

Browse files
committed
feat(actix): AppError as ResponseError; ErrorResponse as Responder; docs/readme
1 parent 357862c commit 96638e3

File tree

2 files changed

+53
-43
lines changed

2 files changed

+53
-43
lines changed

README.md

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
![MSRV](https://img.shields.io/badge/MSRV-1.89-blue)
77
![License](https://img.shields.io/badge/License-MIT%20or%20Apache--2.0-informational)
88

9-
Small, pragmatic error model for API-heavy Rust services. Core is framework-agnostic; integrations are opt-in via feature flags. Stable categories, conservative HTTP mapping, no `unsafe`.
9+
Small, pragmatic error model for API-heavy Rust services.
10+
Core is framework-agnostic; integrations are opt-in via feature flags.
11+
Stable categories, conservative HTTP mapping, no `unsafe`.
1012

1113
- Core types: `AppError`, `AppErrorKind`, `AppResult`, `ErrorResponse`
12-
- Optional Axum `IntoResponse`
14+
- Optional Axum/Actix integration
1315
- Optional OpenAPI schema (via `utoipa`)
1416
- Conversions from `sqlx`, `reqwest`, `redis`, `validator`, `config`, `tokio`
1517

@@ -21,6 +23,7 @@ Small, pragmatic error model for API-heavy Rust services. Core is framework-agno
2123
- **Framework-agnostic core.** No web framework assumptions. No `unsafe`. MSRV pinned. Works in libraries and binaries alike.
2224
- **Opt-in integrations.** Zero default features. You pull only what you need:
2325
- `axum` (HTTP `IntoResponse`)
26+
- `actix` (ready-to-use integration)
2427
- `serde_json` (JSON details)
2528
- `openapi` (schemas via `utoipa`)
2629
- `sqlx`, `reqwest`, `redis`, `validator`, `config`, `tokio`, `multipart` (error conversions)
@@ -36,12 +39,12 @@ Small, pragmatic error model for API-heavy Rust services. Core is framework-agno
3639
```toml
3740
[dependencies]
3841
# lean core, no extra deps
39-
masterror = { version = "0.1", default-features = false }
42+
masterror = { version = "0.2", default-features = false }
4043

4144
# Or with features:
42-
# JSON + Axum + common integrations
43-
# masterror = { version = "0.1", features = [
44-
# "axum", "serde_json", "openapi",
45+
# JSON + Axum/Actix + common integrations
46+
# masterror = { version = "0.2", features = [
47+
# "axum", "actix", "serde_json", "openapi",
4548
# "sqlx", "reqwest", "redis", "validator", "config", "tokio"
4649
# ] }
4750
```
@@ -87,7 +90,11 @@ let resp: ErrorResponse = (&app_err).into();
8790
assert_eq!(resp.status, 404);
8891
```
8992

90-
### Axum integration
93+
---
94+
95+
## Web framework integrations
96+
97+
### Axum
9198

9299
Enable `axum` (and usually `serde_json`) to return errors directly from handlers:
93100

@@ -103,43 +110,35 @@ async fn handler() -> AppResult<&'static str> {
103110
let app = Router::new().route("/demo", get(handler));
104111
```
105112

106-
> Note: for JSON bodies you typically need both `axum` and `serde_json` features enabled.
113+
### Actix
107114

108-
### Actix integration
109-
110-
Enable `actix` (и обычно `serde_json`) чтобы возвращать ошибки и готовый `ErrorResponse`:
115+
Enable `actix` (and usually `serde_json`) to return errors directly from handlers:
111116

112117
```rust
113118
// requires: features = ["actix", "serde_json"]
114119
use actix_web::{get, App, HttpServer, Responder};
115-
use masterror::{AppError, AppErrorKind, ErrorResponse};
120+
use masterror::prelude::*;
116121

117122
#[get("/err")]
118-
async fn err() -> Result<&'static str, AppError> {
119-
Err(AppError::new(AppErrorKind::Forbidden, "No access"))
123+
async fn err() -> AppResult<&'static str> {
124+
Err(AppError::forbidden("No access"))
120125
}
121126

122127
#[get("/payload")]
123128
async fn payload() -> impl Responder {
124129
ErrorResponse::new(422, "Validation failed")
125130
}
126-
127-
# #[actix_web::main]
128-
# async fn main() -> std::io::Result<()> {
129-
# HttpServer::new(|| App::new().service(err).service(payload))
130-
# .bind(("127.0.0.1", 8080))?
131-
# .run()
132-
# .await
133-
# }
134131
```
135132

136-
### OpenAPI
133+
---
134+
135+
## OpenAPI
137136

138137
Enable `openapi` to derive an OpenAPI schema for `ErrorResponse` (via `utoipa`).
139138

140139
```toml
141140
[dependencies]
142-
masterror = { version = "0.1", features = ["openapi", "serde_json"] }
141+
masterror = { version = "0.2", features = ["openapi", "serde_json"] }
143142
utoipa = "5"
144143
```
145144

@@ -148,6 +147,7 @@ utoipa = "5"
148147
## Feature flags
149148

150149
- `axum``IntoResponse` for `AppError` and JSON responses
150+
- `actix``ResponseError`/`Responder` integration
151151
- `openapi` — schema for `ErrorResponse` via `utoipa`
152152
- `serde_json` — JSON details support
153153
- `sqlx``From<sqlx::Error>`
@@ -156,62 +156,72 @@ utoipa = "5"
156156
- `config``From<config::ConfigError>`
157157
- `tokio``From<tokio::time::error::Elapsed>`
158158
- `reqwest``From<reqwest::Error>`
159-
- `multipart` — compatibility flag for projects using multipart in Axum
159+
- `multipart` — compatibility flag for projects using multipart in Axum
160160

161161
---
162162

163163
## Conversions
164164

165165
All mappings are conservative and avoid leaking internals:
166166

167-
- `std::io::Error``Internal`
168-
- `String``BadRequest`
169-
- `sqlx::Error``NotFound` (for `RowNotFound`) or `Database`
170-
- `redis::RedisError``Service`
171-
- `reqwest::Error``Timeout` / `Network` / `ExternalApi`
172-
- `validator::ValidationErrors``Validation`
173-
- `config::ConfigError``Config`
174-
- `tokio::time::error::Elapsed``Timeout`
167+
- `std::io::Error``Internal`
168+
- `String``BadRequest`
169+
- `sqlx::Error``NotFound` (for `RowNotFound`) or `Database`
170+
- `redis::RedisError``Service`
171+
- `reqwest::Error``Timeout` / `Network` / `ExternalApi`
172+
- `validator::ValidationErrors``Validation`
173+
- `config::ConfigError``Config`
174+
- `tokio::time::error::Elapsed``Timeout`
175175

176176
---
177177

178178
## Typical setups
179179

180180
Minimal core:
181+
181182
```toml
182-
masterror = { version = "0.1", default-features = false }
183+
masterror = { version = "0.2", default-features = false }
183184
```
184185

185186
API service (Axum + JSON + common deps):
187+
186188
```toml
187-
masterror = { version = "0.1", features = [
189+
masterror = { version = "0.2", features = [
188190
"axum", "serde_json", "openapi",
189191
"sqlx", "reqwest", "redis", "validator", "config", "tokio"
190192
] }
191193
```
192194

195+
API service (Actix + JSON + common deps):
196+
197+
```toml
198+
masterror = { version = "0.2", features = [
199+
"actix", "serde_json", "openapi",
200+
"sqlx", "reqwest", "redis", "validator", "config", "tokio"
201+
] }
202+
```
203+
193204
---
194205

195206
## Versioning and MSRV
196207

197208
- Semantic versioning. Breaking API or wire-contract changes bump the major version.
198-
- MSRV: 1.89 (may be raised in a **minor** release with a changelog note, never in a patch).
209+
- MSRV: 1.89 (may be raised in a **minor** release with a changelog note, never in a patch).
199210

200211
---
201212

202213
## Non-goals
203214

204215
- Not a general-purpose error aggregator like `anyhow` for CLIs.
205-
- Not a replacement for your domain errors. Use it as the public API surface and transport mapping.
216+
- Not a replacement for your domain errors. Use it as the public API surface and transport mapping.
206217

207218
---
208219

209220
## License
210221

211222
Licensed under either of
212223

213-
- Apache License, Version 2.0
214-
- MIT license
224+
- Apache License, Version 2.0
225+
- MIT license
215226

216227
at your option.
217-

src/response.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,9 @@ mod axum_impl {
187187
//! status derived from `AppErrorKind`.
188188
189189
use axum::{
190+
Json,
190191
http::StatusCode,
191-
response::{IntoResponse, Response},
192-
Json
192+
response::{IntoResponse, Response}
193193
};
194194

195195
use super::ErrorResponse;
@@ -222,7 +222,7 @@ mod axum_impl {
222222
mod actix_impl {
223223
//! Actix `Responder` implementation for `ErrorResponse`.
224224
225-
use actix_web::{body::BoxBody, http::StatusCode, HttpRequest, HttpResponse, Responder};
225+
use actix_web::{HttpRequest, HttpResponse, Responder, body::BoxBody, http::StatusCode};
226226

227227
use super::ErrorResponse;
228228

0 commit comments

Comments
 (0)