actix_web_middleware_redirect_scheme/
service.rs1use actix_service::Service;
2use actix_web::{
3 dev::{ServiceRequest, ServiceResponse},
4 http, Error, HttpResponse,
5};
6use futures::future::{ok, Either, Ready};
7use std::task::{Context, Poll};
8
9pub struct RedirectSchemeService<S> {
10 pub service: S,
11 pub disable: bool,
12 pub https_to_http: bool,
13 pub temporary: bool,
14 pub replacements: Vec<(String, String)>,
15}
16
17type ReadyResult<R, E> = Ready<Result<R, E>>;
18
19impl<S, B> Service for RedirectSchemeService<S>
20where
21 S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
22 S::Future: 'static,
23{
24 type Request = ServiceRequest;
25 type Response = ServiceResponse<B>;
26 type Error = Error;
27 type Future = Either<S::Future, ReadyResult<Self::Response, Self::Error>>;
28
29 fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
30 self.service.poll_ready(cx)
31 }
32
33 fn call(&mut self, req: ServiceRequest) -> Self::Future {
34 if self.disable
35 || (!self.https_to_http && req.connection_info().scheme() == "https")
36 || (self.https_to_http && req.connection_info().scheme() == "http")
37 {
38 Either::Left(self.service.call(req))
39 } else {
40 let host = req.connection_info().host().to_owned();
41 let uri = req.uri().to_owned();
42 let mut url = if self.https_to_http {
43 format!("http://{}{}", host, uri)
44 } else {
45 format!("https://{}{}", host, uri)
46 };
47 for (s1, s2) in self.replacements.iter() {
48 url = url.replace(s1, s2);
49 }
50 Either::Right(ok(req.into_response(
51 if self.temporary {
52 HttpResponse::TemporaryRedirect()
53 } else {
54 HttpResponse::MovedPermanently()
55 }
56 .header(http::header::LOCATION, url)
57 .finish()
58 .into_body(),
59 )))
60 }
61 }
62}