diff --git a/src/app.rs b/src/app.rs
index 1e70860..c02ec4d 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -6,6 +6,37 @@ use tokio::{net::TcpListener, sync::Mutex};
use crate::{handler::Handler, router::Router, Error, ServerError};
+/// App is used to define application-level functionality and initialize the server. Routes are
+/// typically programmed here.
+///
+/// ```ignore
+/// async fn item(
+/// req: Request
,
+/// resp: Option>,
+/// params: Params,
+/// app: App<()>
+/// ) -> HTTPResult {
+/// Ok((
+/// req,
+/// Response::builder().
+/// status(StatusCode::OK).
+/// body(Body::default()).
+/// unwrap()
+/// ))
+/// }
+///
+/// #[tokio::main]
+/// async fn main() -> Result<(), ServerError> {
+/// let app = App::new();
+/// app.get("/:item", compose_handler!(item));
+/// app.serve("localhost:0").await
+/// }
+/// ```
+///
+/// Note that App here has _no state_. It will have a type signature of `App<()>`. To carry state,
+/// look at the `with_state` method which will change the type signature of the `item` call (and
+/// other handlers).
+///
#[derive(Clone)]
pub struct App {
router: Router,
@@ -13,6 +44,7 @@ pub struct App {
}
impl App {
+ /// Construct a new App with no state; it will be passed to handlers as `App<()>`.
pub fn new() -> Self {
Self {
router: Router::new(),
@@ -20,6 +52,11 @@ impl App {
}
}
+ /// Construct an App with state.
+ ///
+ /// This has the type `App` where S is `+ 'static + Clone + Send` and will be passed to
+ /// handlers with the appropriate concrete type.
+ ///
pub fn with_state(state: S) -> Self {
Self {
router: Router::new(),
@@ -27,46 +64,70 @@ impl App {
}
}
+ // FIXME Currently you must await this, seems pointless.
+ /// Return the state of the App. This is returned as `Arc>` and must be acquired under
+ /// lock. In situations where there is no state, [std::option::Option::None] is returned.
pub async fn state(&self) -> Option>> {
self.global_state.clone()
}
+ /// Create a route for a GET request. See [crate::path::Path] and [crate::handler::Handler] for
+ /// more information.
pub fn get(&mut self, path: &str, ch: Handler) {
self.router.add(Method::GET, path.to_string(), ch);
}
+ /// Create a route for a POST request. See [crate::path::Path] and [crate::handler::Handler] for
+ /// more information.
pub fn post(&mut self, path: &str, ch: Handler) {
self.router.add(Method::POST, path.to_string(), ch);
}
+ /// Create a route for a DELETE request. See [crate::path::Path] and [crate::handler::Handler] for
+ /// more information.
pub fn delete(&mut self, path: &str, ch: Handler) {
self.router.add(Method::DELETE, path.to_string(), ch);
}
+ /// Create a route for a PUT request. See [crate::path::Path] and [crate::handler::Handler] for
+ /// more information.
pub fn put(&mut self, path: &str, ch: Handler) {
self.router.add(Method::PUT, path.to_string(), ch);
}
+ /// Create a route for an OPTIONS request. See [crate::path::Path] and
+ /// [crate::handler::Handler] for more information.
pub fn options(&mut self, path: &str, ch: Handler) {
self.router.add(Method::OPTIONS, path.to_string(), ch);
}
+ /// Create a route for a PATCH request. See [crate::path::Path] and
+ /// [crate::handler::Handler] for more information.
pub fn patch(&mut self, path: &str, ch: Handler) {
self.router.add(Method::PATCH, path.to_string(), ch);
}
+ /// Create a route for a HEAD request. See [crate::path::Path] and
+ /// [crate::handler::Handler] for more information.
pub fn head(&mut self, path: &str, ch: Handler) {
self.router.add(Method::HEAD, path.to_string(), ch);
}
+ /// Create a route for a CONNECT request. See [crate::path::Path] and
+ /// [crate::handler::Handler] for more information.
pub fn connect(&mut self, path: &str, ch: Handler) {
self.router.add(Method::CONNECT, path.to_string(), ch);
}
+ /// Create a route for a TRACE request. See [crate::path::Path] and
+ /// [crate::handler::Handler] for more information.
pub fn trace(&mut self, path: &str, ch: Handler) {
self.router.add(Method::TRACE, path.to_string(), ch);
}
+ /// Dispatch a route based on the request. Returns a response based on the error status of the
+ /// handler chain following the normal chain of responsibility rules described elsewhere. Only
+ /// needed by server implementors.
pub async fn dispatch(&self, req: Request) -> Result, Infallible> {
match self.router.dispatch(req, self.clone()).await {
Ok(resp) => Ok(resp),
@@ -83,6 +144,8 @@ impl App {
}
}
+ /// Start a TCP/HTTP server with tokio. Performs dispatch on an as-needed basis. This is a more
+ /// common path for users to start a server.
pub async fn serve(self, addr: &str) -> Result<(), ServerError> {
let socketaddr: SocketAddr = addr.parse()?;
diff --git a/src/lib.rs b/src/lib.rs
index 9386d0b..c7d2c34 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,12 @@
+/// Application/Server-level management and routing configuration; outermost functionality.
pub mod app;
+/// Handler construction and prototypes
pub mod handler;
+/// Macros for quality-of-life when interacting with Handlers
pub mod macros;
+/// Path management for Routes
pub mod path;
+/// Router, Route management and organization
pub mod router;
use http::{Request, Response};
@@ -9,6 +14,7 @@ use std::pin::Pin;
pub(crate) type PinBox = Pin>;
+/// An error for server-related issues.
#[derive(Debug, Clone)]
pub struct ServerError(String);
@@ -21,6 +27,9 @@ where
}
}
+/// General errors for ratpack handlers. Yield either a StatusCode for a literal status, or a
+/// String for a 500 Internal Server Error. Other status codes should be yielded through
+/// [http::Response] returns.
#[derive(Clone, Debug)]
pub enum Error {
StatusCode(http::StatusCode),
@@ -34,6 +43,7 @@ impl Default for Error {
}
impl Error {
+ /// Convenience method to pass anything in that accepts a .to_string method.
pub fn new(message: T) -> Self
where
T: ToString,
@@ -41,6 +51,7 @@ impl Error {
Self::InternalServerError(message.to_string())
}
+ /// A convenient way to return status codes.
pub fn new_status(error: http::StatusCode) -> Self {
Self::StatusCode(error)
}
@@ -55,4 +66,7 @@ where
}
}
+/// HTTPResult is the return type for handlers. If a handler terminates at the end of its chain
+/// with [std::option::Option::None] as the [http::Response], a 500 Internal Server Error will be
+/// returned.
pub type HTTPResult = Result<(Request, Option>), Error>;
diff --git a/src/macros.rs b/src/macros.rs
index c77f13a..c1f1299 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -1,3 +1,9 @@
+/// compose_handler allows you to combine [crate::handler::HandlerFunc] functions into a single [crate::handler::Handler], so that
+/// they cascade through a chain of responsibility. This means that each handler will feed its
+/// output into the input of the next. To start, the first [http::Response] is
+/// [std::option::Option::None], and the final return Response must be non-None otherwise a 500
+/// Internal Server Error is returned. Handlers may do anything they wish to the [http::Request] between
+/// processing periods, including replacing the request entirely.
#[macro_export]
macro_rules! compose_handler {
($( $x:path ),*) => {