actix_web_middleware_redirect_https/
lib.rs1use actix_service::{Service, Transform};
6use actix_web::{
7 dev::{ServiceRequest, ServiceResponse},
8 http, Error, HttpResponse,
9};
10use futures::future::{ok, Either, Ready};
11use std::task::{Context, Poll};
12
13#[derive(Default, Clone)]
28pub struct RedirectHTTPS {
29 replacements: Vec<(String, String)>,
30}
31
32impl RedirectHTTPS {
33 pub fn with_replacements(replacements: &[(String, String)]) -> Self {
49 RedirectHTTPS {
50 replacements: replacements.to_vec(),
51 }
52 }
53}
54
55impl<S, B> Transform<S> for RedirectHTTPS
56where
57 S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
58 S::Future: 'static,
59{
60 type Request = ServiceRequest;
61 type Response = ServiceResponse<B>;
62 type Error = Error;
63 type InitError = ();
64 type Transform = RedirectHTTPSService<S>;
65 type Future = Ready<Result<Self::Transform, Self::InitError>>;
66
67 fn new_transform(&self, service: S) -> Self::Future {
68 ok(RedirectHTTPSService {
69 service,
70 replacements: self.replacements.clone(),
71 })
72 }
73}
74
75pub struct RedirectHTTPSService<S> {
76 service: S,
77 replacements: Vec<(String, String)>,
78}
79
80impl<S, B> Service for RedirectHTTPSService<S>
81where
82 S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
83 S::Future: 'static,
84{
85 type Request = ServiceRequest;
86 type Response = ServiceResponse<B>;
87 type Error = Error;
88 type Future = Either<S::Future, Ready<Result<Self::Response, Self::Error>>>;
89
90 fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
91 self.service.poll_ready(cx)
92 }
93
94 fn call(&mut self, req: ServiceRequest) -> Self::Future {
95 if req.connection_info().scheme() == "https" {
96 Either::Left(self.service.call(req))
97 } else {
98 let host = req.connection_info().host().to_owned();
99 let uri = req.uri().to_owned();
100 let mut url = format!("https://{}{}", host, uri);
101 for (s1, s2) in self.replacements.iter() {
102 url = url.replace(s1, s2);
103 }
104 Either::Right(ok(req.into_response(
105 HttpResponse::MovedPermanently()
106 .header(http::header::LOCATION, url)
107 .finish()
108 .into_body(),
109 )))
110 }
111 }
112}