actix_quick_extract/headers/
origin_or_host.rs

1use actix_web::{http::header::ORIGIN, FromRequest};
2use derive_more::{AsRef, Deref, Display, Into};
3
4use super::HeaderType;
5use crate::ExtractError;
6
7/// Attempts to get the Origin header. If not tries the Host Header
8///
9/// ```no_run
10/// use actix_quick_extract::headers::OriginOrHost;
11/// use actix_web::get;
12/// #[get("/")]
13/// pub async fn index(origin_or_host: OriginOrHost) -> String {
14///     format!("Your origin or host Header is: {}", origin_or_host)
15/// }
16/// ```
17#[derive(Debug, Clone, PartialEq, Eq, Hash, Display, Into, AsRef, Deref)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19#[display("{url}")]
20pub struct OriginOrHost {
21    #[into]
22    #[as_ref(str)]
23    #[deref(forward)]
24    pub url: String,
25    /// Will be none if the header was Host
26    pub is_https: bool,
27}
28
29impl HeaderType for OriginOrHost {
30    #[inline]
31    fn from_request(req: &actix_web::HttpRequest) -> Result<Self, ExtractError> {
32        let (url, https) = if let Some(value) = req.headers().get(ORIGIN) {
33            value
34                .to_str()
35                .map(|value| (value.to_owned(), value.starts_with("https")))
36                .map_err(|v| ExtractError::ToStrError("Origin", v))?
37        } else if let Some(value) = req.headers().get(actix_web::http::header::HOST) {
38            value
39                .to_str()
40                .map(|value| (value.to_owned(), req.connection_info().scheme() == "https"))
41                .map_err(|v| ExtractError::ToStrError("Host", v))?
42        } else {
43            log::debug!("No Origin or Host Header Found");
44            return Err(ExtractError::MissingHeader("Origin or Host"));
45        };
46
47        Ok(OriginOrHost {
48            url,
49            is_https: https,
50        })
51    }
52}
53crate::ready_impl_from_request!(OriginOrHost as Header);