Skip to content

RustServe is a lightweight web server framework built in Rust, created as a learning project to understand the fundamentals of HTTP and server architecture. Inspired by Flask's minimalistic design, it provides a simple, multi-threaded server with basic routing and a flexible templating system for dynamic content.

License

Notifications You must be signed in to change notification settings

vibheksoni/rust-serve

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RustServe: A Simple Web Server in Rust

Welcome to RustServe. This project began as a personal endeavor to deepen my understanding of the Rust programming language by building a web server from the ground up. My primary objective was to explore the fundamental principles of HTTP and server architecture, drawing inspiration from the minimalistic approach of frameworks like Python's Flask. RustServe is designed to be a lightweight, unopinionated server, focusing on clarity of core mechanics rather than providing a comprehensive, production-ready solution.

Repository Link: github.com/vibheksoni/rust-serve


Key Features

  • Lightweight Core: Developed with minimal external dependencies to maintain simplicity and transparency.
  • Multi-threaded Concurrency: Capable of handling multiple client connections simultaneously through Rust's native threading model.
  • Basic Routing: Implements a straightforward routing mechanism to direct incoming requests to designated handler functions based on URL endpoints.
  • Simple Templating System: Includes a rudimentary template engine that facilitates dynamic content generation within HTML files, with built-in HTML escaping for enhanced security.

Getting Started

To set up and run RustServe on your local machine, follow these instructions.

Prerequisites

Ensure you have Rust and Cargo installed. If not, you can obtain them via rustup.rs.

Installation and Execution

  1. Clone the repository:

    git clone https://github.com/vibheksoni/rust-serve.git
  2. Navigate to the project directory:

    cd rust-serve
  3. Run the server:

    cargo run

Upon execution, the server will initiate and display a message indicating it is operational at http://127.0.0.1:8080.


Utilizing RustServe

RustServe is designed for ease of use in defining web server behavior. Its core functionality involves listening for HTTP requests, parsing them, and delegating them to pre-configured handler functions based on the request's endpoint. Responses are then constructed, optionally leveraging a simple templating system, and transmitted back to the client.

Core Components:

  • Server: The central component responsible for managing network connections, route dispatching, and thread management.
  • Request: Encapsulates an incoming HTTP request, providing access to its method, endpoint, headers, query parameters, and body content.
  • Response: Facilitates the creation and transmission of HTTP responses, supporting various content types and a basic HTML templating mechanism.
  • Routes: User-defined functions that dictate the server's behavior for specific URL paths.

For a detailed examination of each component, refer to the dedicated documentation within the docs/ directory.


Code Examples

This section provides practical examples for defining routes and employing the built-in templating system.

Defining a New Route

Route definitions are managed within the src/main.rs file.

  1. Create a Handler Function: This function accepts a reference to the Request object and contains the specific logic for the route.

    // src/main.rs
    
    use crate::modules::request::Request;
    use crate::modules::response::{Response, TemplatePair, ResponseContentType};
    
    fn my_custom_route(req: &Request) {
        let mut res = Response::new(200, req.stream.try_clone().unwrap(), vec![]);
        // Implement your route-specific logic here.
        // Example: Sending a plain text response:
        res.respond("Hello from my custom route!".to_string(), false, None, ResponseContentType::TextPlain).unwrap();
    }
  2. Register the Route in main(): Utilize the app.add_route() method to associate a URL endpoint with your newly defined handler function.

    // src/main.rs
    
    fn main() -> std::io::Result<()> {
        let mut app: Server = Server::new(
            String::from("127.0.0.1"),
            8080,
            true
        );
    
        app.add_route(String::from("/"), index_route);
        // Register your custom route here
        app.add_route(String::from("/custom"), my_custom_route);
    
        println!("Server running on http://{}:{}/", app.host, app.port);
        app.serve();
        Ok(())
    }

Employing the Template System

The server features a basic template system that enables the replacement of placeholders in HTML files with dynamic data.

  1. Prepare an HTML Template: Create an HTML file containing placeholders denoted by the {% key %} syntax.

    <!-- src/index.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>User Profile</title>
    </head>
    <body>
        <h1>Name: {% name %}</h1>
        <h2>Age: {% age %}</h2>
    </body>
    </html>
  2. Utilize res.respond() in your Handler:

    • Specify the file path to your HTML template.
    • Set is_file to true.
    • Provide a Vec<TemplatePair> containing the data for injection.
    • The escape property within TemplatePair dictates whether the corresponding value undergoes HTML escaping to mitigate Cross-Site Scripting (XSS) vulnerabilities.
    // src/main.rs
    
    fn index_route(req: &Request) {
        let mut res = Response::new(
            200,
            req.stream.try_clone().unwrap(),
            vec![]
        );
    
        res.respond(
            // Specify the path to your template file
            String::from("src/index.html"),
            true, // Indicates that 'content' is a file path
            Some(vec![
                TemplatePair {
                    key: String::from("name"),
                    value: String::from("John Doe"),
                    escape: true // Value will be HTML-escaped
                },
                TemplatePair {
                    key: String::from("age"),
                    value: String::from("<script>alert('XSS Attack!')</script>"),
                    escape: true // Value will be HTML-escaped to prevent script execution
                }
            ]),
            ResponseContentType::TextHtml
        ).unwrap();
    }

Comprehensive Documentation

For a deeper dive into the architecture, components, and internal workings of RustServe, consult the detailed documentation files:

  • docs/request.md: An extensive guide to the Request structure and its HTTP request parsing capabilities.
  • docs/response.md: Provides in-depth information on the Response structure, methods for crafting responses, and the templating system.
  • docs/server.md: Explains the Server setup, lifecycle, connection handling, and concurrency model.
  • docs/routing.md: Offers a detailed exploration of how routes are defined, managed, and matched within the server.

Future Enhancements

RustServe is an ongoing learning project, and I have several plans for its continued development and feature expansion:

  • Robust Error Handling: Implementing comprehensive error handling mechanisms to replace current unwrap() calls with Result-based propagation for more graceful failure management.
  • Static File Serving: Adding dedicated support for efficiently serving static assets such as CSS stylesheets, JavaScript files, and images.
  • Middleware Architecture: Integrating a middleware system to enable capabilities like centralized logging, authentication, and request preprocessing.
  • External Configuration: Enhancing flexibility by allowing server settings (e.g., host, port) to be loaded from configuration files or environment variables.
  • Advanced Request Parsing: Developing a more robust and feature-complete request parser to handle complex HTTP scenarios more effectively.
  • HTTPS Support: Incorporating SSL/TLS capabilities to enable secure communication over HTTPS.
  • Comprehensive Test Suite: Expanding the existing test coverage with extensive unit and integration tests to ensure stability and correctness across all components.

License

This project is distributed under the MIT License. Refer to the LICENSE file for complete details.

About

RustServe is a lightweight web server framework built in Rust, created as a learning project to understand the fundamentals of HTTP and server architecture. Inspired by Flask's minimalistic design, it provides a simple, multi-threaded server with basic routing and a flexible templating system for dynamic content.

Topics

Resources

License

Stars

Watchers

Forks