Expand description
§RastAPI
RastAPI is a easy-to-use Rust library for creating low-boilerplate, efficient RESTfull APIs, inspired by FastAPI (Python). You define route handler (functions) and map them with their corresponding url and you have a functioning route. RastAPI follows a Non Blocking IO structure for efficient and conccurent handling of requests. We achieve Non blocking IO by following a Threadpool architecture. We can set the number of threads in the pool before starting the application. RastAPI also has a very efficient LFU-LRU based file caching system.It’s a multi threaded cache system, so we used efficient lock stripping techniques to reduce lock contentions.
§Features
- Minimal boilerplate for defining routes and handlers.
- High performance leveraging Rust’s coccurency and safety.
- Very efficient file uploads and downloads.
§Example
§Text or Json Response
use rastapi::RastAPI;
use rastapi::Request::HttpRequest;
use rastapi::Response::{HttpResponse,create_response};
use rastapi::utils::ContentType;
use std::collections::HashMap;
// Define a Function/Route handler.
// With this exact fucnction signature.
// i.e. fn function_name(request_obj:&HttpRequest,path_params:HashMap<String,String>)->HttpResponse
// request_obj is parameter where all the details of the incoming request is stored.
// path_params is a parameter where url path params are stored. Not confuse it with url query parameters.
// query params are stored in request_obj.params.
fn json(request_obj:&HttpRequest,path_params:HashMap<String,String>)->HttpResponse{
let json_content=r#"{
"name" : "Rony",
"batch" : 2024,
"sem" : 3,
"subjects" : ["OS","Networking","Algorithms"],
"grade" : {
"OS" : "C",
"Cryptography" : "C",
"Algorithms" : "C"
}
}"#;
let resp=create_response(&json_content, 200,ContentType::JSON,true).unwrap(); //create_response(string_content,HTTP_CODE,
return resp; // ContentType,keep_alive_flag)
}
fn main(){
let mut app=RastAPI::new();
// Set number of workers. It indicates total number of simultaneous requests it can serve.
app.set_total_workers(5);
// Map the function/route handler with corresponding url route.
app.register_route("/json",vec!["GET"],json);
app.run("0.0.0.0",5000);
}
§File response
One of the most powerfull features of rastapi is It’s very efficient file uploads downloads. If a file is Not found on system then the server automatically sends 404 Not Found response.
use rastapi::RastAPI;
use rastapi::Request::HttpRequest;
use rastapi::Response::{HttpResponse,send_file};
use rastapi::utils::FileType;
use std::collections::HashMap;
fn file(req:&HttpRequest,path_params:HashMap<String,String>)->HttpResponse{
let mut resp=send_file("file_path/file_name.ext",Some("file_name.ext".to_string()),FileType::MP4,200,true).unwrap(); // send_file0(file_path,file_name
resp.add_header("Header-Name","Header-Value"); // file_type,HTTP_CODE,keep_alive_flag)
return resp;
}
fn main(){
let mut app=RastAPI::new();
app.set_total_workers(5);
app.register_route("/file",vec!["GET"],file);
app.run("127.0.0.1",5000);
}
§Load local enviornment variables and access them from std::env module.
use rastapi::RastAPI;
use rastapi::Request::HttpRequest;
use rastapi::Response::{HttpResponse,send_file};
use rastapi::utils::FileType;
use rastapi::utils::load_env;
use std::collections::HashMap;
use std::env;
fn file(req:&HttpRequest,path_params:HashMap<String,String>)->HttpResponse{
let mut resp=send_file("file_path/file_name.ext",Some("file_name.ext".to_string()),FileType::MP4,200,true).unwrap(); // send_file0(file_path,file_name
resp.add_header("Header-Name","Header-Value"); // file_type,HTTP_CODE,keep_alive_flag)
return resp;
}
fn main(){
load_env::load_env(); // Loads all local enviornment variables in .env file.
let mut app=RastAPI::new();
app.set_total_workers(5);
app.register_route("/file",vec!["GET"],file);
let port:u16=env::var("PORT").unwrap().parse().unwrap();
app.run(env::var("HOST").unwrap().as_str(),port);
}
§Cache
RastAPI uses a slightly tweaked version of a standard LFU-LRU (LFU for eviction and LRU when there is a tie between frequencies of two entity) cache. It only caches files for now. It’s a multi threaded cache So for syncronization we use locks (Mutex). We cann’t use RwLock as for LRU-LFU cache as every read qyery is a write query. So there is a issue of Lock contention. To mitigate lock contention we devided the cache into multiple parts (CacheStore) and lock them individually, thus reducing load on single cache store. We can set total cache size and total number of cache stores.
use rastapi::RastAPI;
fn main(){
let mut app=RastAPI::new();
#[cfg(feature="cachung")]
app.set_cache_config(500,10); // Total cache size is set to 500 MB and
// total number of cache stores set to 10
}
§Persistent Connections
RastAPI supports persistent connections. If you want a route to be persistent then set the keep_alive
flag in create_response
or send_file
as true
.
You can tweak the keep alive behabiour like maximum number of keep alive requests i.e. total number of request response cycle on a signle connection can be set,
default value is 10. You can also set the keep alive timeout, i.e. for how much time we wait for next request after sending a response on persistent connection.
If we don’t recieve new request for this duration then we drop the connection. Default value is 5 seconds.
use rastapi::RastAPI;
fn main(){
let mut app=RastAPI::new();
app.set_keep_alive_time_out(3);
app.set_maximum_keep_alive_requests(10);
app.run("127.0.0.1",5000);
}
§Stop the app
To stop the app gracefully you need to send SIGINT (CTRL + C) or SIGTERM. SIGTSTP(CTRL + Z) is ignored.
Modules§
Macros§
- error
- log_
info - log_
response_ 2xx_ content - log_
response_ 2xx_ file - log_
response_ 3xx_ content - log_
response_ 3xx_ file - log_
response_ 4xx - log_
response_ 5xx - log_
warning
Structs§
- RastAPI
- This is the main API struct. Before doing anything we need to initialize it.