karics
This crate is ported from kanari-network.
But with much ease of use, you can call karics block APIs directly in your service.
Description
karics is a Rust library developed from kanari-network that has been improved for easier use. This library helps you create RESTful APIs quickly without worrying about low-level HTTP handling details.
With karics, you can:
- Define API routes with ease
- Support route matching using regular expressions
- Handle HTTP requests and responses efficiently
- Call API endpoints directly from your service
This library is ideal for developers who want to build web services that are simple, efficient, and easy to maintain.
Usage
First, add this to your Cargo.toml:
[dependencies]
karics = "0.2.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
hyper = "1.6.0"
Then just simply implement your http service
use hyper::{Response, StatusCode, header};
use karics::router::ApiService;
use karics::HttpServiceFactory;
use serde::{Deserialize, Serialize};
use std::io;
use std::sync::{Arc, Mutex};
#[derive(Debug, Clone, Serialize, Deserialize)]
struct User {
id: usize,
name: String,
email: String,
}
struct ApiServiceFactory {
router: Arc<karics::router::Router<Vec<u8>>>,
users: Arc<Mutex<Vec<User>>>,
}
impl HttpServiceFactory for ApiServiceFactory {
type Service = ApiService;
fn new_service(&self, _id: usize) -> Self::Service {
ApiService::with_context(self.router.clone(), self.users.clone())
}
}
fn get_all_users(
users: Arc<Mutex<Vec<User>>>,
) -> impl Fn(Vec<String>) -> Response<Vec<u8>> + Clone {
move |_params| {
let users_guard = users.lock().unwrap();
let users_json = serde_json::to_vec(&*users_guard).unwrap_or_else(|_| b"[]".to_vec());
Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, "application/json")
.body(users_json)
.unwrap()
}
}
fn get_user_by_id(
users: Arc<Mutex<Vec<User>>>,
) -> impl Fn(Vec<String>) -> Response<Vec<u8>> + Clone {
move |params| {
let user_id = params
.get(1)
.and_then(|id| id.parse::<usize>().ok())
.unwrap_or(0);
let users_guard = users.lock().unwrap();
match users_guard.iter().find(|user| user.id == user_id) {
Some(user) => {
let user_json = serde_json::to_vec(user).unwrap();
Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, "application/json")
.body(user_json)
.unwrap()
}
None => Response::builder()
.status(StatusCode::NOT_FOUND)
.header(header::CONTENT_TYPE, "application/json")
.body(r#"{"error":"User not found"}"#.as_bytes().to_vec())
.unwrap(),
}
}
}
fn create_user(users: Arc<Mutex<Vec<User>>>) -> impl Fn(Vec<String>) -> Response<Vec<u8>> + Clone {
move |_params| {
let mut users_guard = users.lock().unwrap();
let new_id = users_guard.len() + 1;
let new_user = User {
id: new_id,
name: format!("User {}", new_id),
email: format!("user{}@example.com", new_id),
};
users_guard.push(new_user.clone());
let user_json = serde_json::to_vec(&new_user).unwrap();
Response::builder()
.status(StatusCode::CREATED)
.header(header::CONTENT_TYPE, "application/json")
.body(user_json)
.unwrap()
}
}
fn main() -> io::Result<()> {
let users = Arc::new(Mutex::new(Vec::<User>::new()));
let mut router = karics::router::Router::new();
router
.get(r"^/users$", get_all_users(users.clone()))
.unwrap();
router
.get(r"^/users/(\d+)$", get_user_by_id(users.clone()))
.unwrap();
router
.post(r"^/users$", create_user(users.clone()))
.unwrap();
let factory = ApiServiceFactory {
router: Arc::new(router),
users,
};
println!("Server running on http://127.0.0.1:8080");
let handle = factory.start("127.0.0.1:8080")?;
handle.join().unwrap();
Ok(())
}
License
This project is licensed under either of
at your option.