Skip to content

Commit 370b342

Browse files
authored
Merge branch 'main' into codex/refactor-contains_nocase-for-performance
2 parents 1ac0078 + abcddf3 commit 370b342

File tree

4 files changed

+60
-5
lines changed

4 files changed

+60
-5
lines changed

CHANGELOG.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@ All notable changes to this project will be documented in this file.
55

66
## [0.10.7] - 2025-10-24
77

8+
### Tests
9+
- Added regression coverage for long classifier needles to exercise the
10+
heap-allocation fallback.
11+
812
### Changed
9-
- Precomputed lowercase Turnkey classifier needles with a stack-backed buffer
13+
- Added an owning `From<AppError>` conversion for `ErrorResponse` and updated the
14+
Axum adapter to use it, eliminating redundant clones when building HTTP error
15+
bodies.
16+
- Precomputed lowercase Turnkey classifier needles with a stack-backed buffer
1017
to remove repeated transformations while keeping the common zero-allocation
1118
path for short patterns.
1219

13-
### Tests
14-
- Added regression coverage for long classifier needles to exercise the
15-
heap-allocation fallback.
1620

1721
## [0.10.6] - 2025-09-21
1822

src/convert/axum.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl IntoResponse for AppError {
7777
#[cfg(feature = "serde_json")]
7878
{
7979
// Build the stable wire contract (includes `code`).
80-
let body: ErrorResponse = (&self).into();
80+
let body: ErrorResponse = self.into();
8181
return body.into_response();
8282
}
8383

src/response/mapping.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,33 @@ impl Display for ErrorResponse {
1313
}
1414
}
1515

16+
impl From<AppError> for ErrorResponse {
17+
fn from(err: AppError) -> Self {
18+
let AppError {
19+
kind,
20+
message,
21+
retry,
22+
www_authenticate
23+
} = err;
24+
25+
let status = kind.http_status();
26+
let code = AppCode::from(kind);
27+
let message = match message {
28+
Some(msg) => msg.into_owned(),
29+
None => String::from("An error occurred")
30+
};
31+
32+
Self {
33+
status,
34+
code,
35+
message,
36+
details: None,
37+
retry,
38+
www_authenticate
39+
}
40+
}
41+
}
42+
1643
impl From<&AppError> for ErrorResponse {
1744
fn from(err: &AppError) -> Self {
1845
let status = err.kind.http_status();

src/response/tests.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,30 @@ fn from_app_error_uses_default_message_when_none() {
147147
assert_eq!(e.message, "An error occurred");
148148
}
149149

150+
#[test]
151+
fn from_owned_app_error_moves_message_and_metadata() {
152+
let err = AppError::unauthorized(String::from("owned message"))
153+
.with_retry_after_secs(5)
154+
.with_www_authenticate("Bearer");
155+
156+
let resp: ErrorResponse = err.into();
157+
158+
assert_eq!(resp.status, 401);
159+
assert!(matches!(resp.code, AppCode::Unauthorized));
160+
assert_eq!(resp.message, "owned message");
161+
assert_eq!(resp.retry.unwrap().after_seconds, 5);
162+
assert_eq!(resp.www_authenticate.as_deref(), Some("Bearer"));
163+
}
164+
165+
#[test]
166+
fn from_owned_app_error_defaults_message_when_absent() {
167+
let resp: ErrorResponse = AppError::bare(AppErrorKind::Internal).into();
168+
169+
assert_eq!(resp.status, 500);
170+
assert!(matches!(resp.code, AppCode::Internal));
171+
assert_eq!(resp.message, "An error occurred");
172+
}
173+
150174
// --- Display formatting --------------------------------------------------
151175

152176
#[test]

0 commit comments

Comments
 (0)