actix_web_httpauth/headers/www_authenticate/challenge/bearer/
challenge.rs1use std::{borrow::Cow, fmt, str};
2
3use actix_web::{
4 http::header::{HeaderValue, InvalidHeaderValue, TryIntoHeaderValue},
5 web::{BufMut, Bytes, BytesMut},
6};
7
8use super::{super::Challenge, BearerBuilder, Error};
9use crate::utils;
10
11#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
39pub struct Bearer {
40 pub(crate) scope: Option<Cow<'static, str>>,
41 pub(crate) realm: Option<Cow<'static, str>>,
42 pub(crate) error: Option<Error>,
43 pub(crate) error_description: Option<Cow<'static, str>>,
44 pub(crate) error_uri: Option<Cow<'static, str>>,
45}
46
47impl Bearer {
48 pub fn build() -> BearerBuilder {
59 BearerBuilder::default()
60 }
61}
62
63#[doc(hidden)]
64impl Challenge for Bearer {
65 fn to_bytes(&self) -> Bytes {
66 let desc_uri_required = self
67 .error_description
68 .as_ref()
69 .map_or(0, |desc| desc.len() + 20)
70 + self.error_uri.as_ref().map_or(0, |url| url.len() + 12);
71
72 let capacity = 6
73 + self.realm.as_ref().map_or(0, |realm| realm.len() + 9)
74 + self.scope.as_ref().map_or(0, |scope| scope.len() + 9)
75 + desc_uri_required;
76
77 let mut buffer = BytesMut::with_capacity(capacity);
78 buffer.put(&b"Bearer"[..]);
79
80 if let Some(ref realm) = self.realm {
81 buffer.put(&b" realm=\""[..]);
82 utils::put_quoted(&mut buffer, realm);
83 buffer.put_u8(b'"');
84 }
85
86 if let Some(ref scope) = self.scope {
87 buffer.put(&b" scope=\""[..]);
88 utils::put_quoted(&mut buffer, scope);
89 buffer.put_u8(b'"');
90 }
91
92 if let Some(ref error) = self.error {
93 let error_repr = error.as_str();
94 let remaining = buffer.remaining_mut();
95 let required = desc_uri_required + error_repr.len() + 9; if remaining < required {
98 buffer.reserve(required);
99 }
100
101 buffer.put(&b" error=\""[..]);
102 utils::put_quoted(&mut buffer, error_repr);
103 buffer.put_u8(b'"')
104 }
105
106 if let Some(ref error_description) = self.error_description {
107 buffer.put(&b" error_description=\""[..]);
108 utils::put_quoted(&mut buffer, error_description);
109 buffer.put_u8(b'"');
110 }
111
112 if let Some(ref error_uri) = self.error_uri {
113 buffer.put(&b" error_uri=\""[..]);
114 utils::put_quoted(&mut buffer, error_uri);
115 buffer.put_u8(b'"');
116 }
117
118 buffer.freeze()
119 }
120}
121
122impl fmt::Display for Bearer {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
124 let bytes = self.to_bytes();
125
126 let repr = str::from_utf8(&bytes)
127 .map_err(|_| fmt::Error)?;
130
131 f.write_str(repr)
132 }
133}
134
135impl TryIntoHeaderValue for Bearer {
136 type Error = InvalidHeaderValue;
137
138 fn try_into_value(self) -> Result<HeaderValue, Self::Error> {
139 HeaderValue::from_maybe_shared(self.to_bytes())
140 }
141}