Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 38 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,13 @@ tokio = { version = "1", features = ["full"] }
2. Write your first code with Ohkami : [examples/quick_start](https://github.com/ohkami-rs/ohkami/blob/main/examples/quick_start/src/main.rs)

```rust,no_run
use ohkami::prelude::*;
use ohkami::typed::status;
use ohkami::{Ohkami, Route, format::Path, typed::status};

async fn health_check() -> status::NoContent {
status::NoContent
}

async fn hello(name: &str) -> String {
async fn hello(Path(name): Path<&str>) -> String {
format!("Hello, {name}!")
}

Expand Down Expand Up @@ -140,7 +139,7 @@ Ohkami responds with HTTP/1.1 `Transfer-Encoding: chunked`.\
Use some reverse proxy to do with HTTP/2,3.

```rust,no_run
use ohkami::prelude::*;
use ohkami::{Ohkami, Route};
use ohkami::sse::DataStream;
use tokio::time::{sleep, Duration};

Expand Down Expand Up @@ -169,7 +168,7 @@ Ohkami only handles `ws://`.\
Use some reverse proxy to do with `wss://`.

```rust,no_run
use ohkami::prelude::*;
use ohkami::{Ohkami, Route};
use ohkami::ws::{WebSocketContext, WebSocket, Message};

async fn echo_text(ctx: WebSocketContext<'_>) -> WebSocket {
Expand Down Expand Up @@ -209,8 +208,8 @@ You don't need to take care of writing accurate methods, paths, parameters, cont
Of course, you can flexibly customize schemas ( by hand-implemetation of `Schema` ), descriptions or other parts ( by `#[operation]` attribute and `openapi_*` hooks ).

```rust,ignore
use ohkami::prelude::*;
use ohkami::typed::status;
use ohkami::{Ohkami, Route};
use ohkami::{format::Json, typed::status};
use ohkami::openapi;

// Derive `Schema` trait to generate
Expand Down Expand Up @@ -300,7 +299,7 @@ rustls-pemfile = "2.2"
```

```rust,no_run
use ohkami::prelude::*;
use ohkami::{Ohkami, Route};
use rustls::ServerConfig;
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
use std::fs::File;
Expand Down Expand Up @@ -370,8 +369,8 @@ Hello, secure ohkami!
*builtin payload* : `Json`, `Text`, `Html`, `UrlEncoded`, `Multipart`

```rust
use ohkami::prelude::*;
use ohkami::typed::status;
use ohkami::{format::Json, typed::status};
use ohkami::serde::{Deserialize, Serialize};

/* Deserialize for request */
#[derive(Deserialize)]
Expand Down Expand Up @@ -399,8 +398,12 @@ async fn create_user(

### Typed params

*builtin params* : `Path`, `Query`

```rust,no_run
use ohkami::prelude::*;
use ohkami::{Ohkami, Route};
use ohkami::format::{Path, Query, Json};
use ohkami::serde::{Deserialize, Serialize};

#[tokio::main]
async fn main() {
Expand All @@ -414,11 +417,13 @@ async fn main() {
)).howl("localhost:5000").await
}

async fn hello(name: &str) -> String {
async fn hello(Path(name): Path<&str>) -> String {
format!("Hello, {name}!")
}

async fn hello_n((name, n): (&str, usize)) -> String {
async fn hello_n(
Path((name, n)): Path<(&str, usize)>
) -> String {
vec![format!("Hello, {name}!"); n].join(" ")
}

Expand Down Expand Up @@ -524,7 +529,7 @@ async fn create_user(
```rust,no_run
use ohkami::{Response, IntoResponse};
use ohkami::serde::Serialize;
use ohkami::format::Json;
use ohkami::format::{Path, Json};
use ohkami::fang::Context;

enum MyError {
Expand All @@ -545,7 +550,7 @@ struct User {
}

async fn get_user(
id: u32,
Path(id): Path<u32>,
Context(pool): Context<'_, sqlx::PgPool>,
) -> Result<Json<User>, MyError> {
let sql = r#"
Expand Down Expand Up @@ -575,22 +580,22 @@ async fn get_user(
### Static directory serving

```rust,no_run
use ohkami::prelude::*;
use ohkami::{Ohkami, Route};

#[tokio::main]
async fn main() {
Ohkami::new((
"/".Dir("./dist"),
"/".Dir("./dist"), // `Route::Dir("path/to/dir")`
)).howl("0.0.0.0:3030").await
}
```

### File upload

```rust,no_run
use ohkami::prelude::*;
use ohkami::typed::status;
use ohkami::format::{Multipart, File};
use ohkami::serde::Deserialize;

#[derive(Deserialize)]
struct FormData<'req> {
Expand Down Expand Up @@ -619,8 +624,9 @@ async fn post_submit(
### Pack of Ohkamis

```rust,no_run
use ohkami::prelude::*;
use ohkami::typed::status;
use ohkami::{Ohkami, Route};
use ohkami::{format::Json, typed::status};
use serde::Serialize;

#[derive(Serialize)]
struct User {
Expand Down Expand Up @@ -667,7 +673,7 @@ async fn main() {
### Testing

```rust
use ohkami::prelude::*;
use ohkami::{Ohkami, Route};
use ohkami::testing::*; // <--

fn hello_ohkami() -> Ohkami {
Expand Down Expand Up @@ -695,7 +701,10 @@ async fn test_my_ohkami() {
### DI by generics

```rust,no_run
use ohkami::prelude::*;
use ohkami::{Ohkami, Route, Response, IntoResponse};
use ohkami::fang::Context;
use ohkami::format::{Json, Path};
use ohkami::serde::Serialize;

//////////////////////////////////////////////////////////////////////
/// errors
Expand All @@ -714,7 +723,7 @@ impl IntoResponse for MyError {
//////////////////////////////////////////////////////////////////////
/// repository

trait Repository: Send + Sync + 'static {
trait UserRepository: Send + Sync + 'static {
fn get_user_by_id(
&self,
id: i64,
Expand All @@ -727,8 +736,8 @@ struct UserRow {
name: String,
}

struct PostgresRepository(sqlx::PgPool);
impl Repository for PostgresRepository {
struct PostgresUserRepository(sqlx::PgPool);
impl UserRepository for PostgresUserRepository {
async fn get_user_by_id(&self, id: i64) -> Result<UserRow, MyError> {
let sql = r#"
SELECT id, name FROM users WHERE id = $1
Expand All @@ -750,8 +759,8 @@ struct User {
name: String,
}

async fn get_user<R: Repository>(
id: u32,
async fn get_user<R: UserRepository>(
Path(id): Path<u32>,
Context(r): Context<'_, R>,
) -> Result<Json<User>, MyError> {
let user_row = r.get_user_by_id(id as i64).await?;
Expand All @@ -762,7 +771,7 @@ async fn get_user<R: Repository>(
}))
}

fn users_ohkami<R: Repository>() -> Ohkami {
fn users_ohkami<R: UserRepository>() -> Ohkami {
Ohkami::new((
"/:id".GET(get_user::<R>),
))
Expand All @@ -774,7 +783,7 @@ fn users_ohkami<R: Repository>() -> Ohkami {
#[tokio::main]
async fn main() {
Ohkami::new((
"/users".By(users_ohkami::<PostgresRepository>()),
"/users".By(users_ohkami::<PostgresUserRepository>()),
)).howl("0.0.0.0:4040").await
}
```
Expand Down
2 changes: 1 addition & 1 deletion examples/quick_start/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ async fn health_check() -> status::NoContent {
status::NoContent
}

async fn hello(name: &str) -> String {
async fn hello(Path(name): Path<&str>) -> String {
format!("Hello, {name}!")
}

Expand Down
11 changes: 6 additions & 5 deletions examples/websocket/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ async fn echo_text(c: WebSocketContext<'_>) -> WebSocket {


async fn echo_text_2(
name: String,
ctx: WebSocketContext<'_>
Path(name): Path<String>,
ctx: WebSocketContext<'_>
) -> EchoTextSession<'_> {
EchoTextSession { name, ctx }
}

struct EchoTextSession<'ws> {
name: String,
ctx: WebSocketContext<'ws>,
ctx: WebSocketContext<'ws>,
}
impl IntoResponse for EchoTextSession<'_> {
fn into_response(self) -> Response {
Expand All @@ -41,7 +41,8 @@ impl IntoResponse for EchoTextSession<'_> {
}


async fn echo_text_3(name: String,
async fn echo_text_3(
Path(name): Path<String>,
ctx: WebSocketContext<'_>
) -> WebSocket {
ctx.upgrade(|c| async {
Expand Down Expand Up @@ -111,7 +112,7 @@ async fn echo_text_3(name: String,
}


async fn echo4(name: String, ws: WebSocketContext<'_>) -> WebSocket {
async fn echo4(Path(name): Path<String>, ws: WebSocketContext<'_>) -> WebSocket {
ws.upgrade(|mut c| async {
/* spawn but not join the handle */
tokio::spawn(async move {
Expand Down
14 changes: 8 additions & 6 deletions ohkami/src/fang/builtin/jwt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ use serde::{Serialize, Deserialize};
///
/// *example.rs*
/// ```no_run
/// use ohkami::prelude::*;
/// use ohkami::typed::status;
/// use ohkami::fang::{Jwt, JwtToken};
///
/// use ohkami::{Ohkami, Route, Response};
/// use ohkami::{format::{Path, Json}, typed::status};
/// use ohkami::fang::{Context, Jwt, JwtToken};
/// use ohkami::serde::{Serialize, Deserialize};
///
/// #[derive(Serialize, Deserialize)]
/// struct OurJwtPayload {
Expand All @@ -46,7 +46,8 @@ use serde::{Serialize, Deserialize};
/// Jwt::default("OUR_JWT_SECRET_KEY")
/// }
///
/// async fn hello(name: &str,
/// async fn hello(
/// Path(name): Path<&str>,
/// Context(auth): Context<'_, OurJwtPayload>
/// ) -> String {
/// format!("Hello {name}, you're authorized!")
Expand Down Expand Up @@ -76,7 +77,8 @@ use serde::{Serialize, Deserialize};
/// async fn main() {
/// Ohkami::new((
/// "/auth".GET(auth),
/// "/private".By(Ohkami::new((our_jwt(),
/// "/private".By(Ohkami::new((
/// our_jwt(),
/// "/hello/:name".GET(hello),
/// )))
/// )).howl("localhost:3000").await
Expand Down
14 changes: 8 additions & 6 deletions ohkami/src/fang/builtin/timeout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,22 @@ use std::time::Duration;
/// ---
/// *example.rs*
/// ```no_run
/// use ohkami::prelude::*;
/// use ohkami::fang::Timeout;
/// use ohkami::{Ohkami, Route};
/// use ohkami::{format::Path, fang::Timeout};
/// use std::time::Duration;
///
/// #[tokio::main]
/// async fn main() {
/// Ohkami::new((Timeout::by_secs(10),
/// Ohkami::new((
/// Timeout::by_secs(10),
/// "/hello/:sleep".GET(sleeping_hello),
/// )).howl("0.0.0.0:3000").await
/// }
///
/// async fn sleeping_hello(sleep: u64) -> &'static str {
/// async fn sleeping_hello(
/// Path(sleep): Path<u64>
/// ) -> &'static str {
/// tokio::time::sleep(Duration::from_secs(sleep)).await;
///
/// "Hello, I was sleeping ):"
/// }
/// ```
Expand Down Expand Up @@ -81,7 +83,7 @@ const _: () = {
use crate::testing::*;

async fn lazy_greeting(
(name, sleep): (&str, u64)
Path((name, sleep)): Path<(&str, u64)>
) -> String {
crate::__rt__::sleep(Duration::from_secs(sleep)).await;

Expand Down
Loading
Loading