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
|
//! The main type is the [`Handler`], which wraps a more specific type of handler and
|
||||||
//! manages delegating responses to it.
|
//! 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 anyhow::Result;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -21,24 +17,63 @@ use crate::{Document, types::{Body, Response, Request}};
|
||||||
|
|
||||||
/// A struct representing something capable of handling a 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
|
/// A crucial part of the documentation for this is the implementations of [`From`], as
|
||||||
/// [`Fn`](std::ops::Fn).
|
/// 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`]
|
/// Detailed descriptions on each variant also describe how each kind of handler works,
|
||||||
/// on it, as this is what can be passed to
|
/// and how they can be created
|
||||||
/// [`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.
|
|
||||||
pub enum Handler {
|
pub enum Handler {
|
||||||
|
|
||||||
/// A handler that responds to a request by delegating to an [`Fn`]
|
/// 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),
|
FnHandler(HandlerInner),
|
||||||
|
|
||||||
/// A handler that always serves an identical response, for any and all request
|
/// 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),
|
StaticHandler(Response),
|
||||||
|
|
||||||
#[cfg(feature = "serve_dir")]
|
#[cfg(feature = "serve_dir")]
|
||||||
/// A handler that serves a directory, including a directory listing
|
/// 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),
|
FilesHandler(PathBuf),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,14 +137,28 @@ where
|
||||||
H: 'static + Fn(Request) -> R + Send + Sync,
|
H: 'static + Fn(Request) -> R + Send + Sync,
|
||||||
R: 'static + Future<Output = Result<Response>> + Send,
|
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.
|
/// 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,
|
/// Don't be overwhelmed by the function signature here. It's honestly way simpler
|
||||||
/// with the request as the first argument. The response provided will be sent to the
|
/// than it looks.
|
||||||
/// 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()).
|
/// # 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 {
|
fn from(handler: H) -> Self {
|
||||||
Self::FnHandler(
|
Self::FnHandler(
|
||||||
Box::new(move|req| Box::pin((handler)(req)) as HandlerResponse)
|
Box::new(move|req| Box::pin((handler)(req)) as HandlerResponse)
|
||||||
|
@ -123,15 +172,14 @@ where
|
||||||
impl From<Response> for Handler {
|
impl From<Response> for Handler {
|
||||||
/// Serve an unchanging response
|
/// 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
|
/// ## Panics
|
||||||
/// This response type **CANNOT** be created using Responses with [`Reader`] bodies.
|
/// This response type **CANNOT** be created using Responses with [`Reader`] bodies.
|
||||||
/// Attempting to do this will cause a panic. Don't.
|
/// Attempting to do this will cause a panic. Don't.
|
||||||
///
|
///
|
||||||
|
/// This will create a [`StaticHandler`]
|
||||||
|
///
|
||||||
/// [`Reader`]: Body::Reader
|
/// [`Reader`]: Body::Reader
|
||||||
|
/// [`StaticHandler`]: Self::StaticHandler
|
||||||
fn from(response: Response) -> Self {
|
fn from(response: Response) -> Self {
|
||||||
#[cfg(debug_assertions)] {
|
#[cfg(debug_assertions)] {
|
||||||
// We have another check once the handler is actually called that is not
|
// 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
|
/// 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
|
/// handler. As with all documents, this will be a successful response with a
|
||||||
/// `text/gemini` MIME.
|
/// `text/gemini` MIME.
|
||||||
|
///
|
||||||
|
/// This will create a [`StaticHandler`]
|
||||||
|
///
|
||||||
|
/// [`StaticHandler`]: Self::StaticHandler
|
||||||
fn from(doc: &Document) -> Self {
|
fn from(doc: &Document) -> Self {
|
||||||
Self::StaticHandler(doc.into())
|
Self::StaticHandler(doc.into())
|
||||||
}
|
}
|
||||||
|
@ -159,18 +211,13 @@ impl From<&Document> for Handler {
|
||||||
impl From<PathBuf> for Handler {
|
impl From<PathBuf> for Handler {
|
||||||
/// Serve files from a directory
|
/// 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
|
/// The path to a single file can be passed in order to serve only a single file for
|
||||||
/// any and all requests.
|
/// any and all requests.
|
||||||
///
|
///
|
||||||
|
/// This will create a [`FilesHandler`].
|
||||||
|
///
|
||||||
/// [`util::serve_dir()`]: crate::util::serve_dir()
|
/// [`util::serve_dir()`]: crate::util::serve_dir()
|
||||||
|
/// [`FilesHandler`]: Handler::FilesHandler
|
||||||
fn from(path: PathBuf) -> Self {
|
fn from(path: PathBuf) -> Self {
|
||||||
Self::FilesHandler(path)
|
Self::FilesHandler(path)
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,11 +230,11 @@ use tokio_rustls::TlsAcceptor;
|
||||||
use rustls::Session;
|
use rustls::Session;
|
||||||
|
|
||||||
mod types;
|
mod types;
|
||||||
|
mod handling;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod routing;
|
pub mod routing;
|
||||||
pub mod handling;
|
|
||||||
#[cfg(feature = "ratelimiting")]
|
#[cfg(feature = "ratelimiting")]
|
||||||
pub mod ratelimiting;
|
mod ratelimiting;
|
||||||
#[cfg(feature = "user_management")]
|
#[cfg(feature = "user_management")]
|
||||||
pub mod user_management;
|
pub mod user_management;
|
||||||
#[cfg(feature = "gemini_srv")]
|
#[cfg(feature = "gemini_srv")]
|
||||||
|
@ -247,6 +247,7 @@ pub use cert::CertGenMode;
|
||||||
|
|
||||||
pub use uriparse as uri;
|
pub use uriparse as uri;
|
||||||
pub use types::*;
|
pub use types::*;
|
||||||
|
pub use handling::Handler;
|
||||||
|
|
||||||
/// The maximun length of a Request URI
|
/// The maximun length of a Request URI
|
||||||
pub const REQUEST_URI_MAX_LEN: usize = 1024;
|
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
|
/// The default port for the gemini protocol
|
||||||
pub const GEMINI_PORT: u16 = 1965;
|
pub const GEMINI_PORT: u16 = 1965;
|
||||||
|
|
||||||
use handling::Handler;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct ServerInner {
|
struct ServerInner {
|
||||||
#[cfg(feature = "gemini_srv")]
|
#[cfg(feature = "gemini_srv")]
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
//! Utilities for routing requests
|
//! 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.
|
//! See [`RoutingNode`] for details on how routes are matched.
|
||||||
|
//!
|
||||||
|
//! [`Server::add_route()`]: crate::Server::add_route
|
||||||
|
|
||||||
use uriparse::path::{Path, Segment};
|
use uriparse::path::{Path, Segment};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue