Expand description
a web framework focus on memory efficiency, composability, and fast compile time.
§Quick start
use xitca_web::{handler::handler_service, route::get, App};
fn main() -> std::io::Result<()> {
App::new()
.at("/", get(handler_service(|| async { "Hello,World!" })))
.serve()
.bind("localhost:8080")?
.run()
.wait()
}
§Memory efficient
- zero copy magic types
- zero cost service tree
§Zero copy
use xitca_web::{
error::Error,
handler::{handler_service, json::LazyJson, path::PathRef},
route::{get, post},
App
};
// PathRef is able to borrow http request's path string as reference
// without copying it.
async fn url_query(PathRef(path): PathRef<'_>) -> &'static str {
println!("{path}");
"zero copy path"
}
// deserializable user type.
#[derive(serde::Deserialize)]
struct User<'a> {
name: &'a str
}
// LazyJson is able to lazily deserialize User type with zero copy &str.
async fn json(lazy: LazyJson<User<'_>>) -> Result<&'static str, Error> {
let User { name } = lazy.deserialize()?;
println!("{name}");
Ok("zero copy json")
}
// Almost all magic extract types in xitca-web utilize zero copy
// to avoid unnecessary memory copy.
App::new()
// a route handling incoming url query.
.at("/query", get(handler_service(url_query)))
// a route handling incoming json object.
.at("/json", post(handler_service(json)))
.serve()
.bind("localhost:8080")?
.run()
.wait()
§Zero cost
use xitca_web::{
handler::{handler_service},
http::WebResponse,
route::get,
middleware::Extension,
service::{Service, ServiceExt},
App, WebContext
};
App::new()
.at("/", get(handler_service(|| async { "hello,world!" })))
// ServiceExt::enclosed_fn combinator enables async function as middleware.
// the async function is unboxed and potentially inlined with other async services
// for efficient binary code with less memory allocation.
.enclosed_fn(middleware_fn)
// ServiceExt::enclosed combinator enables type impl Service trait as middleware.
// the middleware trait method is unboxed and potentially inlined with other async services
// for efficient binary code with less memory allocation.
.enclosed(Extension::new(()))
.serve()
.bind("localhost:8080")?
.run()
.wait()
// a simple middleware just forward request to inner service logic.
async fn middleware_fn<S, T, E>(service: &S, ctx: WebContext<'_>) -> Result<T, E>
where
S: for<'r> Service<WebContext<'r>, Response = T, Error = E>
{
service.call(ctx).await
}
§Composable
- Easy mixture of various level of abstractions and less opinionated APIs
- Common types and traits for cross crates integration of majority rust web ecosystem
§Abstraction variety
use xitca_web::{
body::ResponseBody,
error::Error,
handler::{handler_service, handler_sync_service, FromRequest},
http::{Method, WebResponse},
route::get,
service::fn_service,
App, WebContext
};
App::new()
// high level abstraction. see fn high for detail.
.at("/high", get(handler_service(high)))
// low level abstraction. see fn low for detail.
.at("/low", get(fn_service(low)))
// abstraction for synchronous. see fn sync for detail.
.at("/sync", get(handler_sync_service(sync)))
.serve()
.bind("localhost:8080")?
.run()
.wait()
// magic function with arbitrary receiver type and output type
// that can be extracted from http requests and packed into http
// response.
async fn high(method: &Method) -> &'static str {
// extract http method from http request.
assert_eq!(method, Method::GET);
// pack string literal into http response.
"high level"
}
// function with concrete typed input and output where http types
// are handled manually.
async fn low(ctx: WebContext<'_>) -> Result<WebResponse, Error> {
// manually check http method.
assert_eq!(ctx.req().method(), Method::GET);
// high level abstraction can be opt-in explicitly if desired.
// below is roughly what async fn high did to receive &Method as
// function argument.
let method = <&Method>::from_request(&ctx).await?;
assert_eq!(method, Method::GET);
// manually pack http response.
Ok(WebResponse::new(ResponseBody::from("low level")))
}
// high level abstraction but for synchronous function. this function
// is powered by background thread pool so it does not block the async
// code.
fn sync(method: Method) -> &'static str {
assert_eq!(method, Method::GET);
// blocking thread for long period of time does not impact xitca-web
// async internal.
std::thread::sleep(std::time::Duration::from_secs(3));
"sync"
}
§Middleware composability
use xitca_web::{
error::Error,
handler::{handler_service},
http::WebResponse,
route::get,
service::{Service, ServiceExt},
App, WebContext
};
// ServiceExt::enclosed_fn combinator enables async function as middleware.
// in xitca_web almost all service can be enclosed by an middleware.
App::new()
.at("/",
get(
// apply middleware to handler_service
handler_service(|| async { "hello,world!" })
.enclosed_fn(middleware_fn)
)
// apply middleware to route
.enclosed_fn(middleware_fn)
)
// apply middleware to application
.enclosed_fn(middleware_fn)
.serve()
.bind("localhost:8080")?
.run()
.wait()
// a simple middleware just forward request to inner service logic.
async fn middleware_fn<S, T, E>(service: &S, ctx: WebContext<'_>) -> Result<T, E>
where
S: for<'r> Service<WebContext<'r>, Response = T, Error = E>
{
service.call(ctx).await
}
For more detailed middleware documentation please reference middleware
§Cross crates integration
use tower-http inside xitca-web application.
use tower_http::services::ServeDir;
use xitca_web::{
service::tower_http_compat::TowerHttpCompat,
App
};
App::new()
.at("/", TowerHttpCompat::new(ServeDir::new("/some_folder")))
.serve()
.bind("localhost:8080")?
.run()
.wait()
§Fast compile time
- additive proc macro
- light weight dependency tree
§opt-in proc macro
in xitca-web proc macro is opt-in. This result in a fast compile time with zero public proc macro. That said you still can enable macros for a higher level style of API.
use xitca_web::{codegen::route, App};
#[tokio::main]
async fn main() -> std::io::Result<()> {
App::new()
.at_typed(index)
.serve()
.bind("localhost:8080")?
.run()
.await
}
#[route("/", method = get)]
async fn index() -> &'static str {
"Hello,World!"
}
Re-exports§
pub use body::BodyStream;
Modules§
- http body types and traits.
- re-export of bytes crate types.
- macro code generation module.
- web error types.
- type based high level async function service.
- http types
- middleware types.
- route services.
- service types
- utilities for testing web application
Structs§
- composed application type with router, stateful context and default middlewares.
- multi protocol handling http server
- web context type focus on stateful and side effect based request data access.
Type Aliases§
- type alias for concrete type of nested App.