Preview - Hexilee/roa GitHub Wiki

Roa v0.5

More ergonomic, more effective, and more powerful

Table of Contents

Core

Lockless Context

Locks are removed from the context now!

In version 0.4, you may access the request method like this:

let method = ctx.req().await.method.clone();

But now, you can just borrow it.

let method = &ctx.req.method;

All public fields of context can be accessed by field name.

Rc-less Middleware

In version 0.4, both of middleware itself and context need to be boxed by Rc/Arc before they are passed tohandle method of Middleware (or call method of Endpoint).

But now, they can be passed in pure reference.

use roa::{Context, Result, Endpoint};

async fn endpoint(ctx: &mut Context) -> Result {
    unimplemented!()
}

let mut ctx = Context::fake();
endpoint.call(&mut ctx).await?;

Out-of-the-box State

Now, trait State is just an alias for 'static + Clone + Send + Sync + Sized, and the app.state will be cloned and passed by context when a request inbounds.

use roa::{App, Context, Result};

#[derive(Clone)]
struct State {
    id: i32,
}

async fn endpoint(ctx: &mut Context<State>) -> Result {
    // As Context implement Deref<Target = State> and DerefMut,
    // you can access fields straightly.
    assert_eq!(1, ctx.id);
    ctx.id = 2
    Ok(())
}

// init state with id=1
let app = App::state(State {id: 1}).end(endpoint);

Generic Context Storage

There is an individual storage in each context, you can store or load any data in it.

use roa::{App, Context, Result, Next};

struct Data(i32);

async fn gate(ctx: &mut Context, next: Next<'_>) -> Result {
    ctx.store("id", Data(1));
    next.await
}

async fn end(ctx: &mut Context) -> Result {
    assert_eq!(1, ctx.load::<Data>("id").unwrap().0);
    Ok(())
}

let app = App::new().gate(gate).end(end);

Global Executor

Now you can access global executor by context.

use roa::{Context, Result};

async fn endpoint(ctx: &mut Context) -> Result {
    let id = ctx.exec.spawn(async {1i32}).await;
    let words = ctx.exec.spawn_blocking(|| "Hello, world!").await;
    Ok(())
}

Default Error Code

Now all errors will be cast to Status(500 INTERNAL SERVER ERROR) by default, you can straightly throw unexpected errors!

use roa::{Context, Result};

async fn endpoint(ctx: &mut Context) -> Result {
    let id: usize = "x".parse()?;
    unreachable!()
}

Future Next

In version 0.4, you may call the next middleware by next().await. However, as future in rust won't be executed until you poll(await), it's more reasonable if next is a future rather than a function.

Now, you can call the next middleware by next.await.

use roa::{Context, Result, Next};

async fn gate(ctx: &mut Context, next: Next<'_>') -> Result {
    next.await
}

Extensions

TLS Support

Now roa supports tls, refer to cookbook for more details.

Websocket Support

Now roa supports websocket, refer to cookbook for more details.

Multipart Form Support

Now roa supports multipart form, refer to cookbook for more details.

Integration

Diesel

The roa-diesel crate provides integration of diesel, please refer to docs or integration example for more details.

Tokio-postgres

The roa-pg crate provides integration of tokio-postgres, refer to cookbook for more details.

Juniper

The roa-juniper crate provides integration of juniper. However, you cannot get it from crates.io until juniper v0.14.3 is published.

You can preview this feature in integration-example.

Runtime

Async-std

Roa framework use async runtime and TcpStream of async-std by default. You can disable this feature in Cargo.toml.

roa = { version = "0.5.0", default-features = false}

Tokio

The roa-tokio crate provides tokio-based async runtime and TcpStream.

Refer to cookbook for more details.

⚠️ **GitHub.com Fallback** ⚠️