Skip to main content

r402_http/server/
status.rs

1//! Maps x402 error reasons to HTTP status codes.
2//!
3//! Per x402 v2 §HTTP transport error mapping. The default status for a
4//! payment failure is `402 Payment Required`; a few reasons use other
5//! statuses to signal out-of-band preconditions:
6//!
7//! | [`ErrorReason`]                 | HTTP status              |
8//! | ------------------------------- | ------------------------ |
9//! | [`Permit2AllowanceRequired`]    | `412 Precondition Failed`|
10//! | anything else                   | `402 Payment Required`   |
11//!
12//! [`Permit2AllowanceRequired`]: r402_core::error_reason::ErrorReason::Permit2AllowanceRequired
13
14use http::StatusCode;
15use r402_core::error_reason::ErrorReason;
16
17/// Returns the HTTP status corresponding to an [`ErrorReason`].
18#[must_use]
19pub const fn reason_to_status(reason: &ErrorReason) -> StatusCode {
20    match reason {
21        ErrorReason::Permit2AllowanceRequired => StatusCode::PRECONDITION_FAILED,
22        _ => StatusCode::PAYMENT_REQUIRED,
23    }
24}
25
26#[cfg(test)]
27mod tests {
28    use super::*;
29
30    #[test]
31    fn permit2_allowance_required_maps_to_412() {
32        assert_eq!(
33            reason_to_status(&ErrorReason::Permit2AllowanceRequired),
34            StatusCode::PRECONDITION_FAILED,
35        );
36    }
37
38    #[test]
39    fn other_reasons_map_to_402() {
40        for reason in [
41            ErrorReason::InvalidPayload,
42            ErrorReason::InvalidPaymentRequirements,
43            ErrorReason::InvalidExactEvmPayloadSignature,
44            ErrorReason::InsufficientFunds,
45            ErrorReason::DuplicateSettlement,
46            ErrorReason::InvalidExactSolanaPayloadMemoMismatch,
47            ErrorReason::InvalidTransactionState,
48            ErrorReason::UnexpectedSettleError,
49            ErrorReason::Custom("some_unknown_code".into()),
50        ] {
51            assert_eq!(
52                reason_to_status(&reason),
53                StatusCode::PAYMENT_REQUIRED,
54                "reason {reason:?} should map to 402"
55            );
56        }
57    }
58}