Adapted a type from futures-util allowing us to drop the dep and remove a big chunk of the dep tree

This commit is contained in:
Emi Tatsuo 2020-11-19 11:09:53 -05:00
parent 87d71cb207
commit 475db6af79
Signed by: Emi
GPG key ID: 68FAB2E2E6DFC98B
3 changed files with 34 additions and 4 deletions

View file

@ -21,7 +21,6 @@ mime = "0.3.16"
uriparse = "0.6.3"
percent-encoding = "2.1.0"
futures-core = "0.3.7"
futures-util = "0.3.7"
log = "0.4.11"
webpki = "0.21.0"
lazy_static = "1.4.0"

View file

@ -8,7 +8,6 @@ use std::{
time::Duration,
};
use futures_core::future::BoxFuture;
use futures_util::future::FutureExt;
use tokio::{
prelude::*,
io::{self, BufStream},
@ -33,7 +32,7 @@ pub const REQUEST_URI_MAX_LEN: usize = 1024;
pub const GEMINI_PORT: u16 = 1965;
type Handler = Arc<dyn Fn(Request) -> HandlerResponse + Send + Sync>;
type HandlerResponse = BoxFuture<'static, Result<Response>>;
pub (crate) type HandlerResponse = BoxFuture<'static, Result<Response>>;
#[derive(Clone)]
pub struct Server {
@ -94,7 +93,7 @@ impl Server {
let handler = (self.handler)(request);
let handler = AssertUnwindSafe(handler);
let response = handler.catch_unwind().await
let response = util::HandlerCatchUnwind::new(handler).await
.unwrap_or_else(|_| Response::server_error(""))
.or_else(|err| {
error!("Handler failed: {:?}", err);

View file

@ -11,6 +11,9 @@ use tokio::{
};
#[cfg(feature="serve_dir")]
use crate::types::{Response, Document, document::HeadingLevel::*};
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::task::Poll;
use futures_core::future::Future;
#[cfg(feature="serve_dir")]
pub async fn serve_file<P: AsRef<Path>>(path: P, mime: &Mime) -> Result<Response> {
@ -123,3 +126,32 @@ where
C: AsRef<T> + Into<T::Owned>,
T: ToOwned + ?Sized,
{}
/// A utility for catching unwinds on Futures.
///
/// This is adapted from the futures-rs CatchUnwind, in an effort to reduce the large
/// amount of dependencies tied into the feature that provides this simple struct.
#[must_use = "futures do nothing unless polled"]
pub (crate) struct HandlerCatchUnwind {
future: AssertUnwindSafe<crate::HandlerResponse>,
}
impl HandlerCatchUnwind {
pub(super) fn new(future: AssertUnwindSafe<crate::HandlerResponse>) -> Self {
Self { future }
}
}
impl Future for HandlerCatchUnwind {
type Output = Result<Result<Response>, Box<dyn std::any::Any + Send>>;
fn poll(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context
) -> Poll<Self::Output> {
match catch_unwind(AssertUnwindSafe(|| self.future.as_mut().poll(cx))) {
Ok(res) => res.map(Ok),
Err(e) => Poll::Ready(Err(e))
}
}
}