actix_rewrite/
service.rs

1use std::{ops::Deref, rc::Rc, str::FromStr};
2
3use actix_http::Uri;
4use actix_web::{
5    body::BoxBody,
6    dev::{Service, ServiceRequest, ServiceResponse, forward_ready},
7    error::Error as ActixError,
8};
9use futures_core::future::LocalBoxFuture;
10
11use super::error::Error;
12use super::rewrite::{Engine, Rewrite};
13use super::util;
14
15/// Assembled `mod_rewrite` service
16#[derive(Clone)]
17pub struct RewriteService<S>(pub(crate) Rc<RewriteInner<S>>);
18
19impl<S> Deref for RewriteService<S> {
20    type Target = RewriteInner<S>;
21
22    fn deref(&self) -> &Self::Target {
23        &self.0
24    }
25}
26
27pub struct RewriteInner<S> {
28    pub(crate) service: Rc<S>,
29    pub(crate) engine: Rc<Engine>,
30}
31
32impl<S> Service<ServiceRequest> for RewriteService<S>
33where
34    S: Service<ServiceRequest, Response = ServiceResponse<BoxBody>, Error = ActixError> + 'static,
35    S::Future: 'static,
36{
37    type Response = ServiceResponse<BoxBody>;
38    type Error = ActixError;
39    type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
40
41    forward_ready!(service);
42
43    fn call(&self, mut req: ServiceRequest) -> Self::Future {
44        let this = Rc::clone(&self.0);
45        Box::pin(async move {
46            let uri = match this.engine.rewrite(req.request())? {
47                Rewrite::Uri(uri) => uri,
48                Rewrite::Redirect(res) => return Ok(req.into_response(res)),
49                Rewrite::Response(res) => return Ok(req.into_response(res)),
50            };
51
52            let after = Uri::from_str(&uri).map_err(Error::InvalidUri)?;
53            req.head_mut().uri = util::join_uri(req.uri(), &after)?;
54
55            this.service.call(req).await
56        })
57    }
58}