GithubHelp home page GithubHelp logo

d-holguin / rawrustserver Goto Github PK

View Code? Open in Web Editor NEW
1.0 1.0 0.0 46.07 MB

A multi-threaded HTTP server built using only the Rust standard library, with session-based authentication, an in-memory database, and concurrent request handling.

License: Apache License 2.0

HTML 14.86% Rust 84.83% CSS 0.32%
multithreading rust html http react

rawrustserver's Introduction

RawRustServer

RawRustServer is a multi-threaded web server built in Rust, featuring session-based authentication, an in-memory database, wildcard image support, and a Galactic Bounty Hunter theme. Using only the Rust standard library and no third-party dependencies, this project serves as a hands-on exploration of Rust's concurrency features and HTTP principles.

Table of Contents

Usage

Usage Example

fn main() {
    match run_server() {
        Ok(_) => println!("Server shut down successfully."),
        Err(e) => {
            eprintln!("Failed to run server: {:?}", e);
            std::process::exit(1);
        }
    }
}
fn run_server() -> Result<(), AnyErr> {
    let database = Arc::new(Database::database_init()?);
    let router = Router::new()
        .add_route(
            HttpMethod::get("/home"),
            HomeHandler {
                database: Arc::clone(&database),
            },
        )
        .add_route(HttpMethod::get("/styles.css"), CssHandler)
        .add_route(HttpMethod::get("/favicon.ico"), FaviconHandler)
        .add_route(
            HttpMethod::post("/login"),
            PostLoginHandler {
                database: Arc::clone(&database),
            },
        )
        .add_route(HttpMethod::get("/images/*"), GetImageHandler)
        .add_route(HttpMethod::get("/login"), GetLoginHandler);

    let server = ServerBuilder::new()
        .address("127.0.0.1:8000")
        .thread_count(4)
        .router(router)
        .build()?;
    server.run()
}

// get.rs in the login module
pub struct GetLoginHandler;
impl RouteHandler for GetLoginHandler {
    fn handle(&self, _request: Request) -> Result<Response, AnyErr> {
        let html = include_str!("./login.html").to_string();

        Ok(ResponseBuilder::new()
            .content_type(ContentType::Html)
            .body_string(html)
            .build())
    }
}

ThreadPool

The ThreadPool module is the heart of the server's ability to handle multiple connections concurrently. It maintains a pool of worker threads and provides an interface to execute jobs on these threads. This design allows the server to manage workload effectively and prevent individual requests from blocking the entire server.

Here's a brief look at ThreadPool:

impl ThreadPool {
    pub fn new(size: usize) -> Self {
        assert!(size > 0);
        let (sender, receiver) = mpsc::channel();
        let receiver = Arc::new(Mutex::new(receiver));
        let mut workers = Vec::with_capacity(size);
        for id in 0..size {
            workers.push(Worker::new(id, Arc::clone(&receiver)));
        }

        ThreadPool { workers, sender }
    }
    pub fn execute<F>(&self, f: F)
    where
        F: FnOnce() + Send + 'static,
    {
        let job = Box::new(f);
        self.sender.send(Message::Job(job)).unwrap();
    }
}

Database

RawRustServer includes a simple in-memory database for handling user and session data.

pub struct Database {
    pub users: Arc<SimpleDB<String, User>>,
    pub sessions: Arc<SimpleDB<String, Session>>,
}
impl Database {
    pub fn database_init() -> Result<Database, AnyErr> {
        let users: Arc<SimpleDB<String, User>> = Arc::new(SimpleDB::new());
        let sessions: Arc<SimpleDB<String, Session>> = Arc::new(SimpleDB::new());
        let admin_user = User {
            username: "admin".to_string(),
            password: "hunter12".to_string(),
        };
        users
            .insert(admin_user.username.clone(), admin_user)
            .map_err(|e| AnyErr::wrap("error adding admin credentials to database", e))?;

        Ok(Database { users, sessions })
    }
}

Error Handling

AnyErr serves as a straightforward mechanism for wrapping contextual information around errors, making them more descriptive and easier to debug.

pub struct AnyErr {
    message: String,
    source: Option<Box<dyn Error>>,
}

impl AnyErr {
    pub fn new<M: Into<String>>(message: M) -> Self {
        //...
    }

    pub fn wrap<E: Error + 'static>(message: String, error: E) -> Self {
        //...
    }
}

//Example usage 
if let Some(len) = headers.get("content-length") {
    let len: usize = len
        .parse::<usize>()
        .map_err(|e| AnyErr::wrap("Error parsing content length".to_string(), e))?;
    body.reserve(len);
    while body.len() < len {
        let buffer = reader
            .fill_buf()
            .map_err(|e| AnyErr::wrap("Error reading request body".to_string(), e))?;
        let bytes_to_read = std::cmp::min(buffer.len(), len - body.len());
        body.extend_from_slice(&buffer[..bytes_to_read]);
        reader.consume(bytes_to_read);
    }
}

Logger Utility

The Logger Utility provides a simple and efficient way to log messages both to the terminal and to a file. The logger supports different log levels such as INFO and ERROR.

When logging an INFO message, it will appear in the terminal as:

[INFO] Starting Server...

To use the logger, first initialize the global logger backend with the desired log file name:

logger_backend::init_global_logger("logs/server.log");

Then you can use the logger anywhere in code like this:

logger::info("Starting Server...");

Usage Example

rawrustserver's People

Contributors

d-holguin avatar

Stargazers

Simon Holm avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.