Handlers
The handler
macro has 3 optional arguments in a json like format.
Trailing commas are not supported as of now.
#![allow(unused)] fn main() { #[handler({ container: Container, middleware: { request: [], response: [] }, jobs: { request: [], response: [] } })] }
A request handler is an async function that accepts zero or more arguments.
The arguments can be provided in several ways, by macro attributes.
Handlers bound by a GET
method do not have access to a request body.
The return type must impl darpi::response::Responder
. For convenience, it is implemented for all common types.
possible arguments
- dependency injection container
#[inject] my_arg: Arc<dyn SomeTrait>
- request
#[request] r: darpi::Request<darpi::Body>
consumes the entire request therefore prevents other attributes from being used except#[path]
#[request_parts] rp: &darpi::RequestParts
#[query] q: MyStruct
whereMyStruct
has to implementserde::Deserialize
. Furthermore, if wrapped in anOption
it is not mandatory.#[path] path: MyStruct
whereMyStruct
has to implementserde::Deserialize
./user/{user_id}/article/{article_id}
will deserialize both ids intoMyStruct
.#[body] data: impl FromRequestBody<T: serde:Deserialize>
if handler is not linked to aGET
request
- middleware
#[middleware::request(i) my_arg: T]
wherei
is a literal index of the middleware linked to the handler#[middleware::response(i) my_arg: T]
does not exist (obviously), because response middleware runs after the handler returns
While i recommend using the macros. If you really want to, you could implement the handler trait.
#![allow(unused)] fn main() { use darpi_middleware::body_size_limit; use darpi::{app, handler, response::Responder, Method, Path, Json, Query}; use serde::{Deserialize, Serialize}; #[derive(Deserialize, Serialize, Debug, Path, Query)] pub struct Name { name: String, } #[handler({ middleware: { // roundtrip returns Result<String, Error> // later we can access it via #[middleware::request(0)] request: [roundtrip("blah")] } })] async fn do_something( #[request_parts] _rp: &RequestParts, // the request query is deserialized into Name // if deseriliazation fails, it will result in an error response // to make it optional wrap it in an Option<Name> #[query] query: Name, // the request path is deserialized into Name #[path] path: Name, // the request body is deserialized into the struct Name // it is important to mention that the wrapper around Name // should implement darpi::request::FromRequestBody // Common formats like Json, Xml and Yaml are supported out // of the box but users can implement their own #[body] payload: Json<Name>, // we can access the T from Ok(T) in the middleware result #[middleware::request(0)] m_str: String, // returning a String works because darpi has implemented // the Responder trait for common types ) -> String { format!( "query: {:#?} path: {} body: {} middleware: {}", query, path.name, payload.name, m_str ) } }
An example returning a Response object. For more information visit
#![allow(unused)] fn main() { use darpi::{handler, Body, Response, StatusCode}; #[handler] async fn my_handler() -> Response<Body> { Response::builder() .status(StatusCode::OK) .body(Default::default()) .unwrap() } }