[−][src]Struct roa_core::App
The Application of roa.
Example
use roa_core::App; use log::info; use async_std::fs::File; #[async_std::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let server = App::new(()) .gate_fn(|ctx, next| async move { info!("{} {}", ctx.method().await, ctx.uri().await); next().await }) .end(|ctx| async move { ctx.resp_mut().await.write(File::open("assets/welcome.html").await?); Ok(()) }) .listen("127.0.0.1:8000", |addr| { info!("Server is listening on {}", addr) })?; server.await; Ok(()) }
Model
The Model
and its State
is designed to share data or handler between middlewares.
The only one type implemented Model
by this crate is ()
, you can implement your custom Model if neccassary.
use roa_core::{App, Model}; use log::info; use futures::lock::Mutex; use std::sync::Arc; use std::collections::HashMap; struct AppModel { default_id: u64, database: Arc<Mutex<HashMap<u64, String>>>, } struct AppState { id: u64, database: Arc<Mutex<HashMap<u64, String>>>, } impl AppModel { fn new() -> Self { Self { default_id: 0, database: Arc::new(Mutex::new(HashMap::new())) } } } impl Model for AppModel { type State = AppState; fn new_state(&self) -> Self::State { AppState { id: self.default_id, database: self.database.clone(), } } } #[async_std::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let server = App::new(AppModel::new()) .gate_fn(|ctx, next| async move { ctx.state_mut().await.id = 1; next().await }) .end(|ctx| async move { let id = ctx.state().await.id; ctx.state().await.database.lock().await.get(&id); Ok(()) }) .listen("127.0.0.1:8000", |addr| { info!("Server is listening on {}", addr) })?; server.await; Ok(()) }
Graceful Shutdown
App::listen
returns a hyper::Server, which supports graceful shutdown.
use roa_core::App; use log::info; use futures::channel::oneshot; #[async_std::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // Prepare some signal for when the server should start shutting down... let (tx, rx) = oneshot::channel::<()>(); let server = App::new(()) .listen("127.0.0.1:8000", |addr| { info!("Server is listening on {}", addr) })? .with_graceful_shutdown(async { rx.await.ok(); }); // Await the `server` receiving the signal... server.await; // And later, trigger the signal by calling `tx.send(())`. let _ = tx.send(()); Ok(()) }
Methods
impl<M: Model> App<M>
[src]
pub fn new(model: M) -> Self
[src]
Construct an application from a model.
pub fn gate(&mut self, middleware: impl Middleware<M::State>) -> &mut Self
[src]
Use a middleware.
pub fn gate_fn<F>(
&mut self,
middleware: impl 'static + Sync + Send + Fn(Context<M::State>, Next) -> F
) -> &mut Self where
F: 'static + Send + Future<Output = Result>,
[src]
&mut self,
middleware: impl 'static + Sync + Send + Fn(Context<M::State>, Next) -> F
) -> &mut Self where
F: 'static + Send + Future<Output = Result>,
A sugar to match a lambda as a middleware.
App::gate
cannot match a lambda without parameter type indication.
use roa_core::{App, Next}; let mut app = App::new(()); // app.gate(|_ctx, next| async move { next().await }); compile fails. app.gate(|_ctx, next: Next| async move { next().await });
However, with App::gate_fn
, you can match a lambda without type indication.
use roa_core::{App, Next}; let mut app = App::new(()); app.gate_fn(|_ctx, next| async move { next().await });
pub fn end<F>(&mut self, endpoint: fn(_: Context<M::State>) -> F) -> &mut Self where
F: 'static + Send + Future<Output = Result>,
[src]
F: 'static + Send + Future<Output = Result>,
A sugar to match a function pointer like async fn(Context<S>) -> impl Future
and use it as a middleware(endpoint).
As the ducument of Middleware
, an endpoint is defined as a template:
use roa_core::{App, Context, Result}; use std::future::Future; fn endpoint<F>(ctx: Context<()>) -> F where F: 'static + Send + Future<Output=Result> { unimplemented!() }
However, an async function is not a template,
it needs a transfer function to suit for App::gate
.
use roa_core::{App, Context, Result, State, Middleware}; use std::future::Future; async fn endpoint(ctx: Context<()>) -> Result { Ok(()) } fn transfer<S, F>(endpoint: fn(Context<S>) -> F) -> impl Middleware<S> where S: State, F: 'static + Send + Future<Output=Result> { endpoint } App::new(()).gate(transfer(endpoint));
And App::end
is a wrapper of App::gate
with this transfer function.
use roa_core::App; App::new(()).end(|_ctx| async { Ok(()) });
Trait Implementations
impl<M: Model> Clone for App<M>
[src]
fn clone(&self) -> Self
[src]
fn clone_from(&mut self, source: &Self)
1.0.0[src]
Auto Trait Implementations
impl<M> !RefUnwindSafe for App<M>
impl<M> Send for App<M>
impl<M> Sync for App<M>
impl<M> Unpin for App<M>
impl<M> !UnwindSafe for App<M>
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
type Owned = T
The resulting type after obtaining ownership.
fn to_owned(&self) -> T
[src]
fn clone_into(&self, target: &mut T)
[src]
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,