help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
rust-web-server
/
src
RSK World
rust-web-server
Rust Web Server - High-Performance Async Web Server + WebSocket Support + JWT Authentication + File Upload + Memory Safety + Educational Design
src
  • auth.rs15.7 KB
  • config.rs2.9 KB
  • error.rs5.2 KB
  • file_upload.rs19 KB
  • handlers.rs12.8 KB
  • lib.rs1.8 KB
  • main.rs6 KB
  • middleware.rs6.2 KB
  • static_files.rs9.9 KB
  • utils.rs9.6 KB
  • websocket.rs15.3 KB
package.jsonhandlers.rs
src/handlers.rs
Raw Download
Find: Go to:
/*
 * Request Handlers Module - Rust Web Server
 * 
 * Created by RSK World (https://rskworld.in)
 * Founder: Molla Samser
 * Designer & Tester: Rima Khatun
 * 
 * Contact:
 * - Email: hello@rskworld.in, support@rskworld.in
 * - Phone: +91 93305 39277
 * - Address: Nutanhat, Mongolkote, Purba Burdwan, West Bengal, India, 713147
 * 
 * © 2026 RSK World. All rights reserved.
 * Content used for educational purposes only.
 */

use hyper::{Body, Method, Request, Response, StatusCode};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::sync::RwLock;
use tracing::{error, info};

use crate::error::{ServerError, ServerResult};
use crate::static_files::StaticFileHandler;

/// Shared state for handlers
#[derive(Clone)]
pub struct SharedState {
    pub static_handler: Arc<StaticFileHandler>,
    pub request_count: Arc<RwLock<u64>>,
    pub start_time: Instant,
    pub active_connections: Arc<RwLock<u64>>,
}

impl SharedState {
    pub fn new(static_handler: StaticFileHandler) -> Self {
        Self {
            static_handler: Arc::new(static_handler),
            request_count: Arc::new(RwLock::new(0)),
            start_time: Instant::now(),
            active_connections: Arc::new(RwLock::new(0)),
        }
    }

    pub async fn increment_request_count(&self) {
        let mut count = self.request_count.write().await;
        *count += 1;
    }

    pub async fn get_request_count(&self) -> u64 {
        *self.request_count.read().await
    }

    pub async fn increment_active_connections(&self) {
        let mut count = self.active_connections.write().await;
        *count += 1;
    }

    pub async fn decrement_active_connections(&self) {
        let mut count = self.active_connections.write().await;
        if *count > 0 {
            *count -= 1;
        }
    }

    pub async fn get_active_connections(&self) -> u64 {
        *self.active_connections.read().await
    }

    pub fn get_uptime(&self) -> Duration {
        self.start_time.elapsed()
    }
}

/// Server information structure
#[derive(Debug, Serialize, Deserialize)]
pub struct ServerInfo {
    pub name: String,
    pub version: String,
    pub description: String,
    pub author: String,
    pub contact: ContactInfo,
    pub features: Vec<String>,
    pub technologies: Vec<String>,
}

/// Contact information
#[derive(Debug, Serialize, Deserialize)]
pub struct ContactInfo {
    pub website: String,
    pub email: String,
    pub phone: String,
    pub address: String,
}

/// Server statistics
#[derive(Debug, Serialize, Deserialize)]
pub struct ServerStats {
    pub uptime_seconds: u64,
    pub request_count: u64,
    pub active_connections: u64,
    pub memory_usage_mb: f64,
    pub cpu_usage_percent: f64,
}

/// Echo request/response structure
#[derive(Debug, Serialize, Deserialize)]
pub struct EchoMessage {
    pub message: String,
    pub timestamp: String,
    pub method: String,
    pub path: String,
    pub headers: HashMap<String, String>,
}

/// Handle home page request
pub async fn handle_home(req: Request<Body>, state: &SharedState) -> Response<Body> {
    state.increment_request_count().await;
    
    let html = r#"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Rust Web Server - RSK World</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
        .header { text-align: center; color: #333; }
        .feature { background: #f4f4f4; padding: 10px; margin: 10px 0; border-radius: 5px; }
        .api-link { color: #0066cc; text-decoration: none; }
        .api-link:hover { text-decoration: underline; }
        .footer { text-align: center; margin-top: 40px; color: #666; }
    </style>
</head>
<body>
    <div class="header">
        <h1>🦀 Rust Web Server</h1>
        <p>High-performance async web server built with Rust</p>
    </div>
    
    <div class="features">
        <h2>Features</h2>
        <div class="feature">✅ High performance with async/await</div>
        <div class="feature">✅ Memory safety with Rust</div>
        <div class="feature">✅ Concurrent connections handling</div>
        <div class="feature">✅ Static file serving</div>
        <div class="feature">✅ RESTful API endpoints</div>
        <div class="feature">✅ Error handling and logging</div>
    </div>
    
    <div class="api">
        <h2>API Endpoints</h2>
        <p><a href="/health" class="api-link">GET /health</a> - Server health check</p>
        <p><a href="/api/info" class="api-link">GET /api/info</a> - Server information</p>
        <p><a href="/api/stats" class="api-link">GET /api/stats</a> - Server statistics</p>
        <p>POST /api/echo - Echo service (sends back request data)</p>
    </div>
    
    <div class="footer">
        <p>Created by <strong>RSK World</strong></p>
        <p>Founder: Molla Samser | Designer & Tester: Rima Khatun</p>
        <p>📧 hello@rskworld.in | 📱 +91 93305 39277</p>
        <p>🌐 <a href="https://rskworld.in">https://rskworld.in</a></p>
        <p>© 2026 RSK World. All rights reserved.</p>
    </div>
</body>
</html>
    "#;

    Response::builder()
        .status(StatusCode::OK)
        .header("content-type", "text/html")
        .body(Body::from(html))
        .unwrap_or_else(|_| Response::builder()
            .status(StatusCode::INTERNAL_SERVER_ERROR)
            .body(Body::from("Failed to create home page response"))
            .unwrap())
}

/// Handle health check request
pub async fn handle_health(req: Request<Body>, state: &SharedState) -> Response<Body> {
    state.increment_request_count().await;
    
    let health = serde_json::json!({
        "status": "healthy",
        "timestamp": chrono::Utc::now().to_rfc3339(),
        "uptime_seconds": state.get_uptime().as_secs(),
        "active_connections": state.get_active_connections().await,
    });

    match serde_json::to_string_pretty(&health) {
        Ok(json_str) => Response::builder()
            .status(StatusCode::OK)
            .header("content-type", "application/json")
            .body(Body::from(json_str))
            .unwrap_or_else(|_| Response::builder()
                .status(StatusCode::INTERNAL_SERVER_ERROR)
                .body(Body::from("Failed to create health response"))
                .unwrap()),
        Err(_) => Response::builder()
            .status(StatusCode::INTERNAL_SERVER_ERROR)
            .body(Body::from("Failed to serialize health data"))
            .unwrap(),
    }
}

/// Handle server info request
pub async fn handle_info(req: Request<Body>, state: &SharedState) -> Response<Body> {
    state.increment_request_count().await;
    
    let info = ServerInfo {
        name: "Rust Web Server".to_string(),
        version: "0.1.0".to_string(),
        description: "High-performance web server built with Rust".to_string(),
        author: "RSK World".to_string(),
        contact: ContactInfo {
            website: "https://rskworld.in".to_string(),
            email: "hello@rskworld.in".to_string(),
            phone: "+91 93305 39277".to_string(),
            address: "Nutanhat, Mongolkote, Purba Burdwan, West Bengal, India, 713147".to_string(),
        },
        features: vec![
            "High performance".to_string(),
            "Async request handling".to_string(),
            "Memory safety".to_string(),
            "Concurrent connections".to_string(),
            "Static file serving".to_string(),
            "Systems programming".to_string(),
        ],
        technologies: vec![
            "Rust".to_string(),
            "Tokio".to_string(),
            "Async/Await".to_string(),
            "HTTP Server".to_string(),
            "Memory Safety".to_string(),
            "Concurrency".to_string(),
        ],
    };

    match serde_json::to_string_pretty(&info) {
        Ok(json_str) => Response::builder()
            .status(StatusCode::OK)
            .header("content-type", "application/json")
            .body(Body::from(json_str))
            .unwrap_or_else(|_| Response::builder()
                .status(StatusCode::INTERNAL_SERVER_ERROR)
                .body(Body::from("Failed to create info response"))
                .unwrap()),
        Err(_) => Response::builder()
            .status(StatusCode::INTERNAL_SERVER_ERROR)
            .body(Body::from("Failed to serialize info data"))
            .unwrap(),
    }
}

/// Handle server statistics request
pub async fn handle_stats(req: Request<Body>, state: &SharedState) -> Response<Body> {
    state.increment_request_count().await;
    
    // Get memory usage (simplified)
    let memory_usage = get_memory_usage();
    
    let stats = ServerStats {
        uptime_seconds: state.get_uptime().as_secs(),
        request_count: state.get_request_count().await,
        active_connections: state.get_active_connections().await,
        memory_usage_mb: memory_usage,
        cpu_usage_percent: 0.0, // Simplified - would need actual CPU monitoring
    };

    match serde_json::to_string_pretty(&stats) {
        Ok(json_str) => Response::builder()
            .status(StatusCode::OK)
            .header("content-type", "application/json")
            .body(Body::from(json_str))
            .unwrap_or_else(|_| Response::builder()
                .status(StatusCode::INTERNAL_SERVER_ERROR)
                .body(Body::from("Failed to create stats response"))
                .unwrap()),
        Err(_) => Response::builder()
            .status(StatusCode::INTERNAL_SERVER_ERROR)
            .body(Body::from("Failed to serialize stats data"))
            .unwrap(),
    }
}

/// Handle echo service request
pub async fn handle_echo(req: Request<Body>, state: &SharedState) -> ServerResult<Response<Body>> {
    state.increment_request_count().await;
    
    let body_bytes = hyper::body::to_bytes(req.into_body()).await
        .map_err(|e| ServerError::BadRequest(format!("Failed to read request body: {}", e)))?;
    
    let body_str = String::from_utf8(body_bytes.to_vec())
        .map_err(|e| ServerError::BadRequest(format!("Invalid UTF-8 in request body: {}", e)))?;
    
    let echo_message: EchoMessage = serde_json::from_str(&body_str)
        .unwrap_or_else(|_| EchoMessage {
            message: body_str,
            timestamp: chrono::Utc::now().to_rfc3339(),
            method: "POST".to_string(),
            path: "/api/echo".to_string(),
            headers: HashMap::new(),
        });

    Response::builder()
        .status(StatusCode::OK)
        .header("content-type", "application/json")
        .body(Body::from(serde_json::to_string_pretty(&echo_message).unwrap()))
        .map_err(|e| ServerError::Internal(format!("Failed to create response: {}", e)))
}

/// Handle static file requests
pub async fn handle_static_file(req: Request<Body>, state: &SharedState) -> ServerResult<Response<Body>> {
    state.increment_request_count().await;
    
    let path = req.uri().path();
    let file_path = path.strip_prefix("/").unwrap_or(path);
    
    state.static_handler.serve_file(file_path).await
}

/// Get memory usage in MB
fn get_memory_usage() -> f64 {
    use sysinfo::{System, Pid, ProcessExt, SystemExt};
    
    let mut system = System::new_all();
    system.refresh_all();
    
    // Get current process memory usage
    if let Ok(current_pid) = sysinfo::get_current_pid() {
        if let Some(process) = system.process(current_pid) {
            return process.memory() as f64 / 1024.0 / 1024.0; // Convert from KB to MB
        }
    }
    
    // Fallback to system memory usage if process not found
    system.used_memory() as f64 / 1024.0 / 1024.0 // Convert from KB to MB
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_server_info_serialization() {
        let info = ServerInfo {
            name: "Test Server".to_string(),
            version: "1.0.0".to_string(),
            description: "Test description".to_string(),
            author: "Test Author".to_string(),
            contact: ContactInfo {
                website: "https://example.com".to_string(),
                email: "test@example.com".to_string(),
                phone: "+1234567890".to_string(),
                address: "Test Address".to_string(),
            },
            features: vec!["Feature 1".to_string()],
            technologies: vec!["Tech 1".to_string()],
        };

        let json = serde_json::to_string_pretty(&info).unwrap();
        assert!(json.contains("Test Server"));
        assert!(json.contains("https://example.com"));
    }
}
370 lines•12.8 KB
rust

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer