pavex/cookie/
errors.rs

1//! Errors that can occur when working with cookies.
2use crate::Response;
3use crate::error::UnexpectedError;
4pub use biscotti::errors::*;
5use http::header::ToStrError;
6use pavex_macros::methods;
7
8#[derive(Debug)]
9#[non_exhaustive]
10/// The error type returned by [`extract_request_cookies`](super::extract_request_cookies).
11pub enum ExtractRequestCookiesError {
12    InvalidHeaderValue(ToStrError),
13    MissingPair(MissingPairError),
14    EmptyName(EmptyNameError),
15    Crypto(CryptoError),
16    Decoding(DecodingError),
17    Unexpected(UnexpectedError),
18}
19
20impl std::fmt::Display for ExtractRequestCookiesError {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        match self {
23            ExtractRequestCookiesError::InvalidHeaderValue(_) => {
24                write!(
25                    f,
26                    "Some characters in the `Cookie` header aren't printable ASCII characters"
27                )
28            }
29            _ => {
30                write!(
31                    f,
32                    "Failed to parse request cookies out of the `Cookie` header"
33                )
34            }
35        }
36    }
37}
38
39impl std::error::Error for ExtractRequestCookiesError {
40    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
41        match self {
42            ExtractRequestCookiesError::InvalidHeaderValue(e) => Some(e),
43            ExtractRequestCookiesError::MissingPair(e) => Some(e),
44            ExtractRequestCookiesError::EmptyName(e) => Some(e),
45            ExtractRequestCookiesError::Crypto(e) => Some(e),
46            ExtractRequestCookiesError::Decoding(e) => Some(e),
47            ExtractRequestCookiesError::Unexpected(e) => Some(e),
48        }
49    }
50}
51
52#[methods]
53impl ExtractRequestCookiesError {
54    /// Convert an [`ExtractRequestCookiesError`] into an HTTP response.
55    ///
56    /// It returns a `400 Bad Request` to the caller.
57    /// The body provides details on what exactly went wrong.
58    #[error_handler(pavex = crate)]
59    pub fn into_response(&self) -> Response {
60        use std::fmt::Write as _;
61
62        let mut body = self.to_string();
63        match self {
64            ExtractRequestCookiesError::MissingPair(e) => {
65                write!(body, ". {e}").ok();
66            }
67            ExtractRequestCookiesError::EmptyName(e) => {
68                write!(body, ". {e}").ok();
69            }
70            ExtractRequestCookiesError::Decoding(e) => {
71                write!(body, ". {e}").ok();
72            }
73            ExtractRequestCookiesError::Unexpected(_)
74            | ExtractRequestCookiesError::InvalidHeaderValue(_)
75            | ExtractRequestCookiesError::Crypto(_) => {}
76        }
77        Response::bad_request().set_typed_body(body)
78    }
79}
80
81#[derive(Debug, thiserror::Error)]
82#[non_exhaustive]
83#[error("Some characters in the `Set-Cookie` header value are not printable ASCII characters.")]
84/// The error type returned by [`inject_response_cookies`](super::inject_response_cookies).
85pub struct InjectResponseCookiesError {
86    /// The invalid header value.
87    pub invalid_header_value: String,
88}
89
90#[methods]
91impl InjectResponseCookiesError {
92    /// Convert an [`InjectResponseCookiesError`] into an HTTP response.
93    ///
94    /// It returns a `500 Internal Server Error` to the caller,
95    /// since failure is likely due to misconfiguration or
96    /// mismanagement on the server side.
97    #[error_handler(pavex = crate)]
98    pub fn into_response(&self) -> Response {
99        Response::internal_server_error()
100    }
101}