Redo Handler docs
This commit is contained in:
		
							parent
							
								
									f98b94235a
								
							
						
					
					
						commit
						05089bfea6
					
				
							
								
								
									
										103
									
								
								src/handling.rs
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								src/handling.rs
									
									
									
									
									
								
							|  | @ -2,10 +2,6 @@ | |||
| //!
 | ||||
| //! The main type is the [`Handler`], which wraps a more specific type of handler and
 | ||||
| //! manages delegating responses to it.
 | ||||
| //!
 | ||||
| //! For most purposes, you should never have to manually create any of these structs
 | ||||
| //! yourself, though it may be useful to look at the implementations of [`From`] on
 | ||||
| //! [`Handler`], as these are the things that can be used as handlers for routes.
 | ||||
| use anyhow::Result; | ||||
| 
 | ||||
| use std::{ | ||||
|  | @ -21,24 +17,63 @@ use crate::{Document, types::{Body, Response, Request}}; | |||
| 
 | ||||
| /// A struct representing something capable of handling a request.
 | ||||
| ///
 | ||||
| /// In the future, this may have multiple varieties, but at the minute, it just wraps an
 | ||||
| /// [`Fn`](std::ops::Fn).
 | ||||
| /// A crucial part of the documentation for this is the implementations of [`From`], as
 | ||||
| /// this is what can be passed to [`Server::add_route()`](crate::Server::add_route()) in
 | ||||
| /// order to create a new route.
 | ||||
| ///
 | ||||
| /// The most useful part of the documentation for this is the implementations of [`From`]
 | ||||
| /// on it, as this is what can be passed to
 | ||||
| /// [`Server::add_route()`](crate::Server::add_route()) in order to create a new route.
 | ||||
| /// Each implementation has bespoke docs that describe how the type is used, and what
 | ||||
| /// response is produced.
 | ||||
| /// Detailed descriptions on each variant also describe how each kind of handler works,
 | ||||
| /// and how they can be created
 | ||||
| pub enum Handler { | ||||
| 
 | ||||
|     /// A handler that responds to a request by delegating to an [`Fn`]
 | ||||
|     ///
 | ||||
|     /// Most often created by using the implementation by using the implementation of
 | ||||
|     /// [`From`]
 | ||||
|     ///
 | ||||
|     /// If you're feeling overwhelmed by the function signature, don't panic.  Please see
 | ||||
|     /// the [example](#example).
 | ||||
|     ///
 | ||||
|     /// Any requests passed to the handler will be directly handed down to the handler,
 | ||||
|     /// with the request as the first argument.  The response provided will be sent to the
 | ||||
|     /// requester.  If the handler panics or returns an [`Err`], this will be logged, and
 | ||||
|     /// the requester will be sent a [`TEMPORARY FAILURE`](Response::temporary_failure()).
 | ||||
|     ///
 | ||||
|     /// [`From`]: #impl-From<H>
 | ||||
|     FnHandler(HandlerInner), | ||||
| 
 | ||||
|     /// A handler that always serves an identical response, for any and all request
 | ||||
|     ///
 | ||||
|     /// Any and all requests to this handler will be responded to with the same response,
 | ||||
|     /// no matter what.  This is good for static content that is provided by your app.
 | ||||
|     /// For serving files & directories, try looking at creating a [`FilesHandler`] by
 | ||||
|     /// [passing a directory](#impl-From<PathBuf>).
 | ||||
|     ///
 | ||||
|     /// Most often created by using [`From<Response>`] or [`From<Document>`]
 | ||||
|     ///
 | ||||
|     /// [`FilesHandler`]: Self::FilesHandler
 | ||||
|     /// [`From<Response>`]: #impl-From<Response>
 | ||||
|     /// [`From<Document>`]: #impl-From<%26'_%20Document>
 | ||||
|     StaticHandler(Response), | ||||
| 
 | ||||
|     #[cfg(feature = "serve_dir")] | ||||
|     /// A handler that serves a directory, including a directory listing
 | ||||
|     ///
 | ||||
|     /// Most often created with [`From<PathBuf>`]
 | ||||
|     ///
 | ||||
|     /// Any requests directed to this handler will be served from this path.  For example,
 | ||||
|     /// if a handler serving files from the path `./public/` and bound to `/serve`
 | ||||
|     /// receives a request for `/serve/file.txt`, it will respond with the contents of the
 | ||||
|     /// file at `./public/file.txt`, and automatically infer the MIME type.
 | ||||
|     ///
 | ||||
|     /// This is equivilent to serving files using [`util::serve_dir()`], and as such will
 | ||||
|     /// include directory listings.
 | ||||
|     ///
 | ||||
|     /// Additionally, if the path is only a single file, that file will be served in
 | ||||
|     /// response to *every request*.  That is, adding a handler for `/path/to/file.txt`
 | ||||
|     /// to the route `/hello` will mean that `/hello`, `/hello/file.txt`, and
 | ||||
|     /// `/hello/irrele/vant` will all be responded to with the contents of `file.txt`.
 | ||||
|     ///
 | ||||
|     /// [`From<PathBuf>`]: #impl-From<PathBuf>
 | ||||
|     FilesHandler(PathBuf), | ||||
| } | ||||
| 
 | ||||
|  | @ -102,14 +137,28 @@ where | |||
|     H: 'static + Fn(Request) -> R + Send + Sync, | ||||
|     R: 'static + Future<Output = Result<Response>> + Send, | ||||
| { | ||||
|     /// Wrap an [`Fn`] in a [`Handler`] struct
 | ||||
|     /// Wrap an [`Fn`] in a [`Handler`] struct, creating an [`FnHandler`]
 | ||||
|     ///
 | ||||
|     /// This automatically boxes both the [`Fn`] and the [`Fn`]'s response.
 | ||||
|     ///
 | ||||
|     /// Any requests passed to the handler will be directly handed down to the handler,
 | ||||
|     /// with the request as the first argument.  The response provided will be sent to the
 | ||||
|     /// requester.  If the handler panics or returns an [`Err`], this will be logged, and
 | ||||
|     /// the requester will be sent a [`TEMPORARY FAILURE`](Response::temporary_failure()).
 | ||||
|     /// Don't be overwhelmed by the function signature here.  It's honestly way simpler
 | ||||
|     /// than it looks.
 | ||||
|     ///
 | ||||
|     /// # Example
 | ||||
|     ///
 | ||||
|     /// ```
 | ||||
|     /// # use kochab::*;
 | ||||
|     /// use anyhow::Result;
 | ||||
|     ///
 | ||||
|     /// let handler: Handler = handle_request.into();
 | ||||
|     ///
 | ||||
|     /// async fn handle_request(request: Request) -> Result<Response> {
 | ||||
|     ///     // This could be done with a StaticHandler, but for demonstration:
 | ||||
|     ///     Ok(Response::success_gemini("Hello world!"))
 | ||||
|     /// }
 | ||||
|     /// ```
 | ||||
|     ///
 | ||||
|     /// [`FnHandler`]: Self::FnHandler
 | ||||
|     fn from(handler: H) -> Self { | ||||
|         Self::FnHandler( | ||||
|             Box::new(move|req| Box::pin((handler)(req)) as HandlerResponse) | ||||
|  | @ -123,15 +172,14 @@ where | |||
| impl From<Response> for Handler { | ||||
|     /// Serve an unchanging response
 | ||||
|     ///
 | ||||
|     /// Any and all requests to this handler will be responded to with the same response,
 | ||||
|     /// no matter what.  This is good for static content that is provided by your app.
 | ||||
|     /// For serving files & directories, try looking at creating a handler from a path
 | ||||
|     ///
 | ||||
|     /// ## Panics
 | ||||
|     /// This response type **CANNOT** be created using Responses with [`Reader`] bodies.
 | ||||
|     /// Attempting to do this will cause a panic.  Don't.
 | ||||
|     ///
 | ||||
|     /// This will create a [`StaticHandler`]
 | ||||
|     ///
 | ||||
|     /// [`Reader`]: Body::Reader
 | ||||
|     /// [`StaticHandler`]: Self::StaticHandler
 | ||||
|     fn from(response: Response) -> Self { | ||||
|         #[cfg(debug_assertions)] { | ||||
|             // We have another check once the handler is actually called that is not
 | ||||
|  | @ -150,6 +198,10 @@ impl From<&Document> for Handler { | |||
|     /// This document will be sent in response to any requests that arrive at this
 | ||||
|     /// handler.  As with all documents, this will be a successful response with a
 | ||||
|     /// `text/gemini` MIME.
 | ||||
|     ///
 | ||||
|     /// This will create a [`StaticHandler`]
 | ||||
|     ///
 | ||||
|     /// [`StaticHandler`]: Self::StaticHandler
 | ||||
|     fn from(doc: &Document) -> Self { | ||||
|         Self::StaticHandler(doc.into()) | ||||
|     } | ||||
|  | @ -159,18 +211,13 @@ impl From<&Document> for Handler { | |||
| impl From<PathBuf> for Handler { | ||||
|     /// Serve files from a directory
 | ||||
|     ///
 | ||||
|     /// Any requests directed to this handler will be served from this path.  For example,
 | ||||
|     /// if a handler serving files from the path `./public/` and bound to `/serve`
 | ||||
|     /// receives a request for `/serve/file.txt`, it will respond with the contents of the
 | ||||
|     /// file at `./public/file.txt`.
 | ||||
|     ///
 | ||||
|     /// This is equivilent to serving files using [`util::serve_dir()`], and as such will
 | ||||
|     /// include directory listings.
 | ||||
|     ///
 | ||||
|     /// The path to a single file can be passed in order to serve only a single file for
 | ||||
|     /// any and all requests.
 | ||||
|     ///
 | ||||
|     /// This will create a [`FilesHandler`].
 | ||||
|     ///
 | ||||
|     /// [`util::serve_dir()`]: crate::util::serve_dir()
 | ||||
|     /// [`FilesHandler`]: Handler::FilesHandler
 | ||||
|     fn from(path: PathBuf) -> Self { | ||||
|         Self::FilesHandler(path) | ||||
|     } | ||||
|  |  | |||
|  | @ -230,11 +230,11 @@ use tokio_rustls::TlsAcceptor; | |||
| use rustls::Session; | ||||
| 
 | ||||
| mod types; | ||||
| mod handling; | ||||
| pub mod util; | ||||
| pub mod routing; | ||||
| pub mod handling; | ||||
| #[cfg(feature = "ratelimiting")] | ||||
| pub mod ratelimiting; | ||||
| mod ratelimiting; | ||||
| #[cfg(feature = "user_management")] | ||||
| pub mod user_management; | ||||
| #[cfg(feature = "gemini_srv")] | ||||
|  | @ -247,6 +247,7 @@ pub use cert::CertGenMode; | |||
| 
 | ||||
| pub use uriparse as uri; | ||||
| pub use types::*; | ||||
| pub use handling::Handler; | ||||
| 
 | ||||
| /// The maximun length of a Request URI
 | ||||
| pub const REQUEST_URI_MAX_LEN: usize = 1024; | ||||
|  | @ -254,8 +255,6 @@ pub const REQUEST_URI_MAX_LEN: usize = 1024; | |||
| /// The default port for the gemini protocol
 | ||||
| pub const GEMINI_PORT: u16 = 1965; | ||||
| 
 | ||||
| use handling::Handler; | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| struct ServerInner { | ||||
|     #[cfg(feature = "gemini_srv")] | ||||
|  |  | |||
|  | @ -1,6 +1,12 @@ | |||
| //! Utilities for routing requests
 | ||||
| //!
 | ||||
| //! For most users, this is more advanced than you need to get.  If you're interested in
 | ||||
| //! adding routes, please see [`Server::add_route()`], which is how most people will
 | ||||
| //! interact with the routing API
 | ||||
| //!
 | ||||
| //! See [`RoutingNode`] for details on how routes are matched.
 | ||||
| //!
 | ||||
| //! [`Server::add_route()`]: crate::Server::add_route
 | ||||
| 
 | ||||
| use uriparse::path::{Path, Segment}; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue