2021-05-30 13:24:03 +02:00
|
|
|
use self::{
|
2021-05-31 10:20:07 +02:00
|
|
|
body::Body,
|
2021-05-31 16:28:26 +02:00
|
|
|
routing::{AlwaysNotFound, RouteAt},
|
2021-05-30 13:24:03 +02:00
|
|
|
};
|
2021-05-29 21:13:06 +02:00
|
|
|
use bytes::Bytes;
|
2021-05-31 10:20:07 +02:00
|
|
|
use futures_util::ready;
|
|
|
|
|
use http::Response;
|
2021-05-30 01:11:18 +02:00
|
|
|
use pin_project::pin_project;
|
2021-05-29 21:13:06 +02:00
|
|
|
use std::{
|
|
|
|
|
future::Future,
|
2021-05-30 01:11:18 +02:00
|
|
|
pin::Pin,
|
2021-05-29 21:13:06 +02:00
|
|
|
task::{Context, Poll},
|
|
|
|
|
};
|
2021-05-31 10:20:07 +02:00
|
|
|
use tower::Service;
|
2021-05-29 21:13:06 +02:00
|
|
|
|
2021-05-30 13:24:03 +02:00
|
|
|
pub mod body;
|
|
|
|
|
pub mod extract;
|
|
|
|
|
pub mod handler;
|
|
|
|
|
pub mod response;
|
|
|
|
|
pub mod routing;
|
|
|
|
|
|
|
|
|
|
mod error;
|
2021-05-30 04:28:24 +02:00
|
|
|
|
2021-05-31 12:22:16 +02:00
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests;
|
|
|
|
|
|
2021-05-30 13:24:03 +02:00
|
|
|
pub use self::error::Error;
|
2021-05-29 21:13:06 +02:00
|
|
|
|
2021-05-31 16:28:26 +02:00
|
|
|
pub fn app() -> App<AlwaysNotFound> {
|
2021-05-29 21:13:06 +02:00
|
|
|
App {
|
2021-05-31 16:28:26 +02:00
|
|
|
service_tree: AlwaysNotFound(()),
|
2021-05-29 21:13:06 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-30 00:52:04 +02:00
|
|
|
#[derive(Debug, Clone)]
|
2021-05-29 21:13:06 +02:00
|
|
|
pub struct App<R> {
|
2021-05-31 16:28:26 +02:00
|
|
|
service_tree: R,
|
2021-05-29 21:13:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<R> App<R> {
|
2021-05-30 00:52:04 +02:00
|
|
|
pub fn at(self, route_spec: &str) -> RouteAt<R> {
|
|
|
|
|
self.at_bytes(Bytes::copy_from_slice(route_spec.as_bytes()))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn at_bytes(self, route_spec: Bytes) -> RouteAt<R> {
|
|
|
|
|
RouteAt {
|
2021-05-29 21:13:06 +02:00
|
|
|
app: self,
|
2021-05-30 00:52:04 +02:00
|
|
|
route_spec,
|
2021-05-29 21:13:06 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-30 04:28:24 +02:00
|
|
|
pub struct IntoService<R> {
|
|
|
|
|
app: App<R>,
|
|
|
|
|
poll_ready_error: Option<Error>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<R> Clone for IntoService<R>
|
2021-05-29 21:13:06 +02:00
|
|
|
where
|
2021-05-30 04:28:24 +02:00
|
|
|
R: Clone,
|
|
|
|
|
{
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
app: self.app.clone(),
|
|
|
|
|
poll_ready_error: None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<R, B, T> Service<T> for IntoService<R>
|
|
|
|
|
where
|
|
|
|
|
R: Service<T, Response = Response<B>>,
|
2021-05-30 02:29:41 +02:00
|
|
|
R::Error: Into<Error>,
|
2021-05-30 04:28:24 +02:00
|
|
|
B: Default,
|
2021-05-29 21:13:06 +02:00
|
|
|
{
|
2021-05-30 04:28:24 +02:00
|
|
|
type Response = Response<B>;
|
|
|
|
|
type Error = Error;
|
|
|
|
|
type Future = HandleErrorFuture<R::Future, B>;
|
2021-05-29 21:13:06 +02:00
|
|
|
|
2021-05-30 00:52:04 +02:00
|
|
|
#[inline]
|
2021-05-29 21:13:06 +02:00
|
|
|
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
2021-05-31 16:28:26 +02:00
|
|
|
if let Err(err) = ready!(self.app.service_tree.poll_ready(cx)).map_err(Into::into) {
|
2021-05-30 13:24:03 +02:00
|
|
|
self.poll_ready_error = Some(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Poll::Ready(Ok(()))
|
2021-05-29 21:13:06 +02:00
|
|
|
}
|
|
|
|
|
|
2021-05-30 00:52:04 +02:00
|
|
|
fn call(&mut self, req: T) -> Self::Future {
|
2021-05-30 04:28:24 +02:00
|
|
|
if let Some(poll_ready_error) = self.poll_ready_error.take() {
|
2021-05-30 13:24:03 +02:00
|
|
|
match error::handle_error::<B>(poll_ready_error) {
|
2021-05-30 04:28:24 +02:00
|
|
|
Ok(res) => {
|
|
|
|
|
return HandleErrorFuture(Kind::Response(Some(res)));
|
|
|
|
|
}
|
|
|
|
|
Err(err) => {
|
|
|
|
|
return HandleErrorFuture(Kind::Error(Some(err)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-31 16:28:26 +02:00
|
|
|
HandleErrorFuture(Kind::Future(self.app.service_tree.call(req)))
|
2021-05-29 21:13:06 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-30 04:28:24 +02:00
|
|
|
#[pin_project]
|
|
|
|
|
pub struct HandleErrorFuture<F, B>(#[pin] Kind<F, B>);
|
|
|
|
|
|
|
|
|
|
#[pin_project(project = KindProj)]
|
|
|
|
|
enum Kind<F, B> {
|
|
|
|
|
Response(Option<Response<B>>),
|
|
|
|
|
Error(Option<Error>),
|
|
|
|
|
Future(#[pin] F),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<F, B, E> Future for HandleErrorFuture<F, B>
|
2021-05-30 00:52:04 +02:00
|
|
|
where
|
2021-05-30 04:28:24 +02:00
|
|
|
F: Future<Output = Result<Response<B>, E>>,
|
|
|
|
|
E: Into<Error>,
|
|
|
|
|
B: Default,
|
2021-05-30 00:52:04 +02:00
|
|
|
{
|
2021-05-30 04:28:24 +02:00
|
|
|
type Output = Result<Response<B>, Error>;
|
2021-05-30 00:52:04 +02:00
|
|
|
|
2021-05-30 04:28:24 +02:00
|
|
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
|
|
|
match self.project().0.project() {
|
|
|
|
|
KindProj::Response(res) => Poll::Ready(Ok(res.take().unwrap())),
|
|
|
|
|
KindProj::Error(err) => Poll::Ready(Err(err.take().unwrap())),
|
|
|
|
|
KindProj::Future(fut) => match ready!(fut.poll(cx)) {
|
|
|
|
|
Ok(res) => Poll::Ready(Ok(res)),
|
2021-05-30 13:24:03 +02:00
|
|
|
Err(err) => Poll::Ready(error::handle_error(err.into())),
|
2021-05-30 04:28:24 +02:00
|
|
|
},
|
|
|
|
|
}
|
2021-05-30 00:52:04 +02:00
|
|
|
}
|
2021-05-30 04:28:24 +02:00
|
|
|
}
|