1use std::convert::Infallible;
2
3use actix_utils::future::{ok, Ready};
4use actix_web::{dev::Payload, FromRequest, HttpRequest};
5
6#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct Host(String);
11
12impl_more::impl_as_ref!(Host => String);
13impl_more::impl_into!(Host => String);
14impl_more::forward_display!(Host);
15
16impl Host {
17 pub fn into_inner(self) -> String {
19 self.0
20 }
21}
22
23impl FromRequest for Host {
24 type Error = Infallible;
25 type Future = Ready<Result<Self, Self::Error>>;
26
27 #[inline]
28 fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
29 ok(Host(req.connection_info().host().to_owned()))
30 }
31}
32
33#[cfg(test)]
34mod tests {
35 use actix_web::{
36 http::StatusCode,
37 test::{self, TestRequest},
38 web, App, HttpResponse,
39 };
40
41 use super::*;
42
43 #[actix_web::test]
44 async fn extracts_host() {
45 let app =
46 test::init_service(App::new().default_service(web::to(|host: Host| async move {
47 HttpResponse::Ok().body(host.to_string())
48 })))
49 .await;
50
51 let req = TestRequest::default()
52 .insert_header(("host", "in-header.com"))
53 .to_request();
54 let res = test::call_service(&app, req).await;
55 assert_eq!(res.status(), StatusCode::OK);
56 assert_eq!(test::read_body(res).await, b"in-header.com".as_ref());
57
58 let req = TestRequest::default().uri("http://in-url.com").to_request();
59 let res = test::call_service(&app, req).await;
60 assert_eq!(res.status(), StatusCode::OK);
61 assert_eq!(test::read_body(res).await, b"in-url.com".as_ref());
62
63 let req = TestRequest::default().to_request();
64 let res = test::call_service(&app, req).await;
65 assert_eq!(res.status(), StatusCode::OK);
66 assert_eq!(test::read_body(res).await, b"localhost:8080".as_ref());
67 }
68}