amoeba 1.0.1

A lightweight HTTP API library for Rust
Documentation
use amoeba::prelude::*;

struct User(String);

impl User {
    fn from_request(req: &Request) -> Result<Self, &'static str> {
        let data = match &req.body {
            Some(b) => Ok(&b.data),
            None => Err("User not provided"),
        }?;

        let Ok(user) = std::str::from_utf8(data) else {
            return Err("Name not UTF-8 compatible");
        };

        Ok(Self(user.into()))
    }
}

struct Users(Vec<User>);

impl Users {
    fn to_str(&self) -> String {
        self.0
            .iter()
            .map(|u| &u.0)
            .fold(String::new(), |mut acc, u| {
                acc.push_str(&format!("{}\n", u));
                acc
            })
    }

    fn find(&self, user: &User) -> Option<usize> {
        self.0
            .iter()
            .enumerate()
            .find(|(_, u)| u.0 == user.0)
            .map(|(i, _)| i)
    }
}

fn get_users(users: &mut Users, _: Request) -> Result<Response, HttpError> {
    Ok(Response::new()
        .body(ContentType::PlainText, users.to_str().into_bytes())
        .status(200))
}

fn add_user(users: &mut Users, req: Request) -> Result<Response, HttpError> {
    let user = User::from_request(&req).map_err(|e| HttpError::new(e))?;
    users.0.push(user);
    Ok(Response::new())
}

fn remove_user(users: &mut Users, req: Request) -> Result<Response, HttpError> {
    let user = User::from_request(&req).map_err(|e| HttpError::new(e))?;

    let index = users
        .find(&user)
        .ok_or(HttpError::new("User not found").status(404))?;

    users.0.remove(index);

    Ok(Response::new())
}

fn main() -> Result<(), std::io::Error> {
    Server::new("localhost:8080", Users(Vec::new()))
        .route(Route::new("GET", "/users", get_users))
        .route(Route::new("POST", "/users", add_user))
        .route(Route::new("DELETE", "/users", remove_user))
        .run()
}