actix_web_httpauth/extractors/
errors.rs1use std::{error::Error, fmt};
2
3use actix_web::{http::StatusCode, HttpResponse, ResponseError};
4
5use crate::headers::www_authenticate::{Challenge, WwwAuthenticate};
6
7#[derive(Debug)]
12pub struct AuthenticationError<C: Challenge> {
13 challenge: C,
14 status_code: StatusCode,
15}
16
17impl<C: Challenge> AuthenticationError<C> {
18 pub fn new(challenge: C) -> AuthenticationError<C> {
22 AuthenticationError {
23 challenge,
24 status_code: StatusCode::UNAUTHORIZED,
25 }
26 }
27
28 pub fn challenge_mut(&mut self) -> &mut C {
30 &mut self.challenge
31 }
32
33 pub fn status_code_mut(&mut self) -> &mut StatusCode {
38 &mut self.status_code
39 }
40}
41
42impl<C: Challenge> fmt::Display for AuthenticationError<C> {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 fmt::Display::fmt(&self.status_code, f)
45 }
46}
47
48impl<C: Challenge + 'static> Error for AuthenticationError<C> {}
49
50impl<C: Challenge + 'static> ResponseError for AuthenticationError<C> {
51 fn status_code(&self) -> StatusCode {
52 self.status_code
53 }
54
55 fn error_response(&self) -> HttpResponse {
56 HttpResponse::build(self.status_code())
57 .insert_header(WwwAuthenticate(self.challenge.clone()))
58 .finish()
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use actix_web::Error;
65
66 use super::*;
67 use crate::headers::www_authenticate::basic::Basic;
68
69 #[test]
70 fn test_status_code_is_preserved_across_error_conversions() {
71 let ae = AuthenticationError::new(Basic::default());
72 let expected = ae.status_code;
73
74 let err = Error::from(ae);
76 let res_err = err.as_response_error();
77 assert_eq!(expected, res_err.status_code());
78 }
79}