[−][src]Crate roa_core
Introduction
Roa is an async web framework inspired by koajs, lightweight but powerful.
Application
A Roa application is a structure containing a middleware group which composes and executes middleware functions in a stack-like manner.
The obligatory hello world application:
use roa_core::App; use log::info; use std::error::Error as StdError; #[async_std::main] async fn main() -> Result<(), Box<dyn StdError>> { let mut app = App::new(()); app.end(|ctx| async move { ctx.resp_mut().await.write_str("Hello, World"); Ok(()) }); app.listen("127.0.0.1:8000", |addr| { info!("Server is listening on {}", addr) })? .await?; Ok(()) }
Cascading
The following example responds with "Hello World", however, the request flows through
the logging
middleware to mark when the request started, then continue
to yield control through the response middleware. When a middleware invokes next().await
the function suspends and passes control to the next middleware defined. After there are no more
middleware to execute downstream, the stack will unwind and each middleware is resumed to perform
its upstream behaviour.
use roa_core::App; use log::info; use std::error::Error as StdError; use std::time::Instant; #[async_std::main] async fn main() -> Result<(), Box<dyn StdError>> { let mut app = App::new(()); app.gate_fn(|_ctx, next| async move { let inbound = Instant::now(); next().await?; info!("time elapsed: {} ms", inbound.elapsed().as_millis()); Ok(()) }); app.end(|ctx| async move { ctx.resp_mut().await.write_str("Hello, World"); Ok(()) }); app.listen("127.0.0.1:8000", |addr| { info!("Server is listening on {}", addr) })? .await?; Ok(()) }
Error Handling
You can catch or straightly throw a Error returned by next.
use roa_core::{App, throw}; use async_std::task::spawn; use http::StatusCode; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let (addr, server) = App::new(()) .gate_fn(|ctx, next| async move { // catch if let Err(err) = next().await { // teapot is ok if err.status_code != StatusCode::IM_A_TEAPOT { return Err(err) } } Ok(()) }) .gate_fn(|ctx, next| async move { next().await?; // just throw unreachable!() }) .end(|_ctx| async move { throw!(StatusCode::IM_A_TEAPOT, "I'm a teapot!") }) .run_local()?; spawn(server); let resp = reqwest::get(&format!("http://{}", addr)).await?; assert_eq!(StatusCode::OK, resp.status()); Ok(()) }
error_handler
App has an error_handler to handle Error
thrown by the top middleware.
This is the error_handler:
use roa_core::{Context, Error, Result, Model, ErrorKind}; pub async fn error_handler<M: Model>(context: Context<M>, err: Error) -> Result { context.resp_mut().await.status = err.status_code; if err.expose { context.resp_mut().await.write_str(&err.message); } if err.kind == ErrorKind::ServerError { Err(err) } else { Ok(()) } }
The Error thrown by this error_handler will be handled by hyper.
Use custom runtime.
Use hyper::Server::builder to construct a hyper server with your custom runtime.
Example
use roa_core::{App, Server, AddrIncoming, Executor}; use std::future::Future; /// An implementation of hyper::rt::Executor based on tokio #[derive(Copy, Clone)] pub struct Exec; impl<F> Executor<F> for Exec where F: 'static + Send + Future, F::Output: 'static + Send, { #[inline] fn execute(&self, fut: F) { tokio::task::spawn(fut); } } #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let app = App::new(()); let server = Server::builder(AddrIncoming::bind("127.0.0.1:8080")?) .executor(Exec) .serve(app); server.await?; Ok(()) }
Modules
header | HTTP header types |
Macros
throw | Throw an |
Structs
AddrIncoming | A stream of connections from binding to an address. As an implementation of hyper::server::accept::Accept. |
App | The Application of roa. |
Body | The Body of Request and Response. |
Bucket | A wrapper of |
Context | A structure to share request, response and other data between middlewares. |
Error | The |
Request | Http request type of roa. |
Response | Http response type of roa. |
Server | A listening HTTP server that accepts connections in both HTTP1 and HTTP2 by default. |
StatusCode | An HTTP status code ( |
Variable | A wrapper of String. |
Enums
ErrorKind | Kind of Error. |
Traits
Executor | An executor of futures. |
Middleware | Middleware |
Model | The |
State | The |
Functions
join | Join two middleware. |
join_all | Join all middlewares in a vector. |
Type Definitions
BodyCallback | Callback when body is finished. |
Next | Type of the second parameter in a middleware. |
Result | Type alias for |
ResultFuture | Type alias for |
Attribute Macros
async_trait |