about halfway done with API docs

Signed-off-by: Erik Hollensbe <linux@hollensbe.org>
This commit is contained in:
Erik Hollensbe
2022-01-21 16:37:21 -08:00
parent 3d01cb23b8
commit 6be31f3c30
3 changed files with 83 additions and 0 deletions
+63
View File
@@ -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<Body>,
/// resp: Option<Response<Body>>,
/// 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<S: Clone + Send> {
router: Router<S>,
@@ -13,6 +44,7 @@ pub struct App<S: Clone + Send> {
}
impl<S: 'static + Clone + Send> App<S> {
/// 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<S: 'static + Clone + Send> App<S> {
}
}
/// Construct an App with state.
///
/// This has the type `App<S>` 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<S: 'static + Clone + Send> App<S> {
}
}
// FIXME Currently you must await this, seems pointless.
/// Return the state of the App. This is returned as `Arc<Mutex<S>>` 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<Arc<Mutex<S>>> {
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<S>) {
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<S>) {
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<S>) {
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<S>) {
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<S>) {
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<S>) {
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<S>) {
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<S>) {
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<S>) {
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<Body>) -> Result<Response<Body>, Infallible> {
match self.router.dispatch(req, self.clone()).await {
Ok(resp) => Ok(resp),
@@ -83,6 +144,8 @@ impl<S: 'static + Clone + Send> App<S> {
}
}
/// 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()?;
+14
View File
@@ -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<F> = Pin<Box<F>>;
/// 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<T>(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<hyper::Body>, Option<Response<hyper::Body>>), Error>;
+6
View File
@@ -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 ),*) => {