rush_sync_server/server/
redirect.rs

1// src/server/redirect.rs
2use crate::core::prelude::*;
3use actix_web::{web, App, HttpRequest, HttpResponse, HttpServer};
4
5/// HTTP→HTTPS Redirect Server - Teil des Server-Systems
6pub struct HttpRedirectServer {
7    port: u16,
8    target_port: u16,
9}
10
11impl HttpRedirectServer {
12    pub fn new(port: u16, target_port: u16) -> Self {
13        Self { port, target_port }
14    }
15
16    async fn redirect_handler(req: HttpRequest, target_port: web::Data<u16>) -> HttpResponse {
17        let host = req
18            .headers()
19            .get("host")
20            .and_then(|v| v.to_str().ok())
21            .unwrap_or("localhost");
22
23        // Host ohne Port
24        let host_clean = host.split(':').next().unwrap_or(host);
25
26        let path = req.uri().path();
27        let query = req.uri().query().unwrap_or("");
28
29        // Redirect URL bauen
30        let redirect_url = if *target_port.get_ref() == 443 {
31            format!("https://{}{}", host_clean, path)
32        } else {
33            format!("https://{}:{}{}", host_clean, target_port.get_ref(), path)
34        };
35
36        let final_url = if !query.is_empty() {
37            format!("{}?{}", redirect_url, query)
38        } else {
39            redirect_url
40        };
41
42        log::debug!("HTTP→HTTPS: {} → {}", req.uri(), final_url);
43
44        HttpResponse::MovedPermanently()
45            .insert_header(("Location", final_url))
46            .insert_header(("Strict-Transport-Security", "max-age=31536000"))
47            .finish()
48    }
49
50    pub async fn run(self) -> Result<()> {
51        log::info!("HTTP redirect server starting on port {}", self.port);
52        log::info!("Redirecting to HTTPS port {}", self.target_port);
53
54        let target_port = self.target_port;
55
56        HttpServer::new(move || {
57            App::new()
58                .app_data(web::Data::new(target_port))
59                .default_service(web::route().to(Self::redirect_handler))
60        })
61        .bind(("0.0.0.0", self.port))
62        .map_err(|e| AppError::Validation(format!("Port {} bind failed: {}", self.port, e)))?
63        .run()
64        .await
65        .map_err(|e| AppError::Io(e))
66    }
67}