A web api framework with speed and safety in mind.
One of the big goals is to catch all errors at compile time
, if possible.
The framework uses hyper and ideally, the performance should be as if you were using hyper
yourself.
The framework also uses shaku for compile time
verifiable dependency injection.
The framework is in early development. All feedback is appreciated.
An example of a simple app
Cargo.toml
[dependencies]
darpi = {git = "https://github.com/petar-dambovaliev/darpi.git", branch = "master"}
serde = { version = "1.0", features = ["derive"] }
tokio = {version = "0.2.11", features = ["full"]}
shaku = {version = "0.5.0", features = ["thread_safe"]}
main.rs
```rust
use asynctrait::asynctrait;
use darpi::{
app, handler, middleware, middleware::Expect, pathtype, querytype, request::ExtractBody,
response::ResponderError, Body, Json, Method, Path, Query, RequestParts,
};
use derive_more::{Display, From};
use serde::{Deserialize, Serialize};
use shaku::{module, Component, Interface};
use std::sync::Arc;
use UserRole::Admin;
///////////// setup dependencies with shaku ///////////
struct UserExtractorImpl;
impl UserExtractor for UserExtractorImpl {
async fn extract(&self, p: &RequestParts) -> Result
trait UserExtractor: Interface {
async fn extract(&self, p: &RequestParts) -> Result
module! { Container { components = [UserExtractorImpl, MyLogger], providers = [], } }
fn make_container() -> Container { Container::builder().build() }
////////////////////////
enum Error { #[display(fmt = "no auth header")] NoAuthHeaderError, #[display(fmt = "Access denied")] AccessDenied, }
impl ResponderError for Error {}
enum UserRole { Regular, Admin, }
// there are 2 types of middleware Request
and Response
// the constant argument that needs to be present is &RequestParts
// everything else is up to the user
// Arc
async fn accesscontrol(
userroleextractor: Arc
if expected_role > actual_role {
return Err(Error::AccessDenied);
}
Ok(())
}
pub struct Name { name: String, }
// Path
async fn helloworld(p: Path
// the handler macro has 2 optional arguments
// the shaku container type and a collection of middlewares
// the enum variant Admin
is corresponding to the middlewre access_control
's Expect
async fn do_something(p: Path
#[tokio::main]
async fn main() -> Result<(), darpi::Error> {
// the app
macro creates a server and allows the user to call
// the method run
and await on that future
app!({
// if the address is a string literal, it is verified at compile time
// if it is a string variable, obviously, it won't
address: "127.0.0.1:3000",
// via the container we inject our dependencies
// in this case, MyLogger type
// any handler that has the trait Logger as an argument
// will be given MyLogger
module: makecontainer => Container,
bind: [
{
// When a path argument is defined in the route,
// the handler is required to have Path