ohkami 0.9.0

declarative web framework for nightly Rust
docs.rs failed to build ohkami-0.9.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: ohkami-0.24.3

ohkami - [狼] wolf in Japanese - is declarative web framework for nightly Rust.

Features

  • macro free, declarative APIs
  • supporting multi runtimetokio, async-std (and more in future)

Quick start

  1. Add to dependencies:
# this sample uses `tokio` runtime.
# you can choose `async-std` instead.

[dependencies]
ohkami = { version = "0.9.0", features = ["rt_tokio"] }
tokio  = { version = "1",     fetures  = ["full"] }

(And check if your Rust toolchains are nightly ones)

  1. Write your first code with ohkami:
use ohkami::prelude::*;

async fn health_check(c: Context) -> Response {
    c.NoContent()
}

async fn hello(c: Context, name: String) -> Response {
    c.OK().text(format!("Hello, {name}!"))
}

#[tokio::main]
async fn main() {
    Ohkami::new()(
        "/hc"   .GET(health_check),
        "/:name".GET(hello),
    ).howl(3000).await
}

Samples

handle path/query params

use ohkami::prelude::*;
use ohkami::utils::Query;


#[tokio::main]
async fn main() {
    Ohkami::new()(
        "/api/users/:id".
            GET(get_user).
            PATCH(update_user),
    ).howl("localhost:5000").await
}

async fn get_user(c: Context,
    id: usize /* <-- path param */
) -> Response {

    // ...

    c.OK().json(found_user)
}


#[Query]
struct UpdateUserQuery {
    q: Option<u64>
}

async fn update_user(c: Context,
    id:    usize,        /* <-- path  params */
    query: GetUserQuery, /* <-- query params */
) -> Response {

    // ...

    c.NoContent()
}

Use tuple like (verion, id): (u8, usize), for multiple path params.

handle request body

use ohkami::{prelude::*, utils::Payload};


#[Payload(JSON)]
struct CreateUserRequest {
    name:     String,
    password: String,
}

async fn create_user(c: Context,
    req: CreateUserRequest
) -> Response {

    // ...

    c.NoContent()
}


#[Payload(URLEncoded)]
struct LoginInput {
    name:     String,
    password: String,
}

#[derive(serde::Serialize)]
struct Credential {
    token: String,
}

async fn post_login(c: Context,
    input: LoginInput
) -> Response {

    // ...

    let token = // ...

    c.OK().json(Credential { token })
}

use middlewares

ohkami's middlewares are called "fangs".

#[tokio::main]
async fn main() {
    Ohkami::with((append_server))(
        "/"  .GET(root),
        "/hc".GET(health_check),
        "/api/users".
            GET(get_users).
            POST(create_user),
    ).howl(":8080").await
}

fn append_server(c: &mut Context) {
    c.headers
        .Server("ohkami");
}

pack of Ohkamis

#[tokio::main]
async fn main() {
    // ...

    let users_ohkami = Ohkami::new()(
        "/".
            POST(create_user),
        "/:id".
            GET(get_user).
            PATCH(update_user).
            DELETE(delete_user),
    );

    Ohkami::new()(
        "/hc"       .GET(health_check),
        "/api/users".By(users_ohkami), // <-- nest by `By`
    ).howl(5000).await
}

error handling

Use .map_err(|e| c. /* error_method */ )?

async fn handler1(c: Context) -> Response {
    make_result()
        .map_err(|e| c.InternalServerError())?;
}

async fn handler2(c: Context) -> Response {
    let user = generate_dummy_user()
        .map_err(|e| c.InternalServerError()
            .text("in `generate_dummy_user`"))?;
}

License

ohkami is licensed under MIT LICENSE (LICENSE-MIT or https://opensource.org/licenses/MIT).