use actix_http::{StatusCode, Uri};
use actix_web::http::header;
use actix_web::{HttpRequest, HttpResponse};
use mod_rewrite::context::{EngineCtx, ServerCtx};
use crate::Middleware;
use super::error::Error;
use super::util;
pub enum Rewrite {
Uri(Uri),
Redirect(HttpResponse),
Response(HttpResponse),
}
pub struct Engine {
engine: mod_rewrite::Engine,
srv_ctx: ServerCtx,
}
impl Engine {
pub fn new() -> Self {
Self {
engine: mod_rewrite::Engine::default(),
srv_ctx: ServerCtx::default(),
}
}
pub fn max_iterations(mut self, iterations: usize) -> Self {
self.engine = self.engine.max_iterations(iterations);
self
}
pub fn server_context(mut self, ctx: ServerCtx) -> Self {
self.srv_ctx = ctx;
self
}
pub fn add_rules(&mut self, rules: &str) -> Result<&mut Self, Error> {
self.engine.add_rules(rules)?;
Ok(self)
}
pub fn rewrite(&self, req: &HttpRequest) -> Result<Rewrite, Error> {
let mut ctx = EngineCtx::default()
.with_env()
.with_time()
.with_ctx(util::request_ctx(req))
.with_ctx(self.srv_ctx.clone());
Ok(
match self.engine.rewrite_ctx(&req.uri().to_string(), &mut ctx)? {
mod_rewrite::Rewrite::Uri(uri) => Rewrite::Uri(util::recode(uri)?),
mod_rewrite::Rewrite::EndUri(uri) => Rewrite::Uri(util::recode(uri)?),
mod_rewrite::Rewrite::Redirect(uri, sc) => Rewrite::Redirect(
HttpResponse::build(StatusCode::from_u16(sc)?)
.insert_header((header::LOCATION, uri))
.body(""),
),
mod_rewrite::Rewrite::StatusCode(sc) => {
Rewrite::Response(HttpResponse::new(StatusCode::from_u16(sc)?))
}
},
)
}
#[inline]
pub fn middleware(self) -> Middleware {
self.into()
}
}
impl Default for Engine {
fn default() -> Self {
Self::new()
}
}