ohkami

ohkami - [狼] means wolf in Japanese - is simple and macro free web framework for Rust.


Features


Quick start

  1. Add dependencies:

toml [dependencies] ohkami = "0.3"

  1. Write your first code with ohkami:

```rust use ohkami::prelude::*;

fn main() -> Result<()> { Server::setup() .GET("/", || async { Response::OK("Hello, world!") }) .serve_on(":3000") } ```

  1. If you're interested in ohkami, learn more by examples and documentation!


Snippets

handle query params

rust let name = ctx.query::<&str>("name")?; // if presumable, `::<&str>` isn't needed rust let count = ctx.query::<usize>("count")?; // if presumable, `::<usize>` isn't needed

handle request body

rust let body = ctx.body::<D>()?; // if presumable, `::<D>` isn't needed // `D` has to be `serde::Deserialize`

handle path params

```rust fn main() -> Result<()> { Server::setup() .GET("/sleepy/:time/:name", sleepyhello) .serveon(":3000") }

async fn sleepyhello(time: u64, name: String) -> Result { (time < 30) .else(|| Response::BadRequest("sleeping time (sec) must be less than 30."))?; std::thread::sleep( std::time::Duration::from_secs(time) ); Response::OK(format!("Hello {name}, I'm extremely sleepy...")) } ```

return OK response with text/plain

rust Response::OK("Hello, world!")

return OK response with application/json

rust Response::OK(JSON("Hello, world!")) rust Response::OK(json!("ok": true)) rust Response::OK(json(user)?) // serialize Rust value into JSON // value's type has to be `serde::Serialize`

handle errors

```rust let user = ctx.body::()?;

// or, you can add an error context message: let user = ctx.body::() .else(|e| e.errorcontext("failed to get user data"))?;

// or discard original error: let user = ctx.body::() .else(|| Response::InternalServerError("can't get user"))?; // or .else(|| Response::InternalServerError(None))?; ```

handle Option values

rust let handler = self.handler.as_ref()._else(|| Response::NotFound(None))?;

assert boolean conditions

rust (count < 10) ._else(|| Response::BadRequest("`count` must be less than 10"))?; // or ._else(|| Response::BadRequest(None))?;

log config

rust fn main() -> Result<()> { let config = Config { log_subscribe: Some( tracing_subscriber::fmt() .with_max_level(tracing::Level::TRACE) ), ..Default::default() }; Server::setup_with(config) .GET("/", |_| async {Response::OK("Hello!")}) }

DB config

rust let config = Config { db_profile: DBprofile { pool_options: PgPoolOptions::new().max_connections(20), url: DB_URL.as_str(), }, ..Default::default() };

use sqlx

rust let user = sqlx::query_as::<_, User>( "SELECT id, name FROM users WHERE id = $1" ).bind(1) .fetch_one(ctx.pool()) .await?; // `Response` implements `From<sqlx::Error>`

test

  1. split setup process from main function: rust fn server() -> Server { Server::setup() .GET("/", || async {Response::OK("Hello!")}) } fn main() -> Result<()> { server().serve_on(":3000") }
  2. write tests using assert_to_res , assert_not_to_res: ```rust

    [cfg(test)]

mod test { use ohkami::{server::Server, response::Response, testsystem::{Test, Request, Method}}; use oncecell::sync::Lazy;

static SERVER: Lazy<Server> = Lazy::new(|| super::server());

#[test]
fn test_hello() {
    let request = Request::new(Method::GET, "/");
    (*SERVER).assert_to_res(&request, Response::OK("Hello!"));
    (*SERVER).assert_not_to_res(&request, Response::BadRequest(None));
}

} ```


Development

ohkami is on early stage now and not for producntion use.\ Please give me your feedback! → GetHub issue


License

This project is under MIT LICENSE (LICENSE-MIT or https://opensource.org/licenses/MIT).