1use http::{HeaderName, HeaderValue, StatusCode};
2use x402_core::{transport::PaymentRequired, types::Base64EncodedHeader};
3
4#[derive(Debug, Clone)]
6pub struct ErrorResponse {
7 pub status: StatusCode,
8 pub header: ErrorResponseHeader,
9 pub body: Box<PaymentRequired>,
13}
14
15#[derive(Debug, Clone)]
17pub enum ErrorResponseHeader {
18 PaymentRequired(Base64EncodedHeader),
19 PaymentResponse(Base64EncodedHeader),
20}
21
22impl ErrorResponseHeader {
23 pub fn header_value(self) -> Option<(HeaderName, HeaderValue)> {
27 match self {
28 ErrorResponseHeader::PaymentRequired(Base64EncodedHeader(s)) => {
29 HeaderValue::from_str(&s)
30 .ok()
31 .map(|v| (HeaderName::from_static("payment-required"), v))
32 }
33 ErrorResponseHeader::PaymentResponse(Base64EncodedHeader(s)) => {
34 HeaderValue::from_str(&s)
35 .ok()
36 .map(|v| (HeaderName::from_static("payment-response"), v))
37 }
38 }
39 }
40}
41
42#[cfg(feature = "axum")]
43impl axum::response::IntoResponse for ErrorResponse {
44 fn into_response(self) -> axum::response::Response {
45 let mut response = (self.status, axum::extract::Json(self.body)).into_response();
46 if let Some((name, val)) = self.header.header_value() {
47 response.headers_mut().insert(name, val);
48 }
49 response
50 }
51}