Files
axum/src/lib.rs
T

125 lines
2.7 KiB
Rust
Raw Normal View History

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::{
2021-06-01 00:34:09 +02:00
convert::Infallible,
2021-05-29 21:13:06 +02:00
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;
2021-05-31 12:22:16 +02:00
#[cfg(test)]
mod tests;
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>,
}
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(),
}
}
}
impl<R, B, T> Service<T> for IntoService<R>
where
2021-06-01 00:34:09 +02:00
R: Service<T, Response = Response<B>, Error = Infallible>,
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>;
2021-06-01 00:34:09 +02:00
type Error = Infallible;
type Future = HandleErrorFuture<R::Future>;
2021-05-29 21:13:06 +02:00
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
2021-06-01 00:34:09 +02:00
match ready!(self.app.service_tree.poll_ready(cx)) {
Ok(_) => Poll::Ready(Ok(())),
Err(err) => match err {},
2021-05-30 13:24:03 +02:00
}
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-06-01 00:34:09 +02:00
HandleErrorFuture(self.app.service_tree.call(req))
2021-05-29 21:13:06 +02:00
}
}
2021-05-30 04:28:24 +02:00
#[pin_project]
2021-06-01 00:34:09 +02:00
pub struct HandleErrorFuture<F>(#[pin] F);
2021-05-30 04:28:24 +02:00
2021-06-01 00:34:09 +02:00
impl<F, B> Future for HandleErrorFuture<F>
2021-05-30 00:52:04 +02:00
where
2021-06-01 00:34:09 +02:00
F: Future<Output = Result<Response<B>, Infallible>>,
2021-05-30 04:28:24 +02:00
B: Default,
2021-05-30 00:52:04 +02:00
{
2021-06-01 00:34:09 +02:00
type Output = Result<Response<B>, Infallible>;
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> {
2021-06-01 00:34:09 +02:00
self.project().0.poll(cx)
}
}
pub(crate) trait ResultExt<T> {
fn unwrap_infallible(self) -> T;
}
impl<T> ResultExt<T> for Result<T, Infallible> {
fn unwrap_infallible(self) -> T {
match self {
Ok(value) => value,
Err(err) => match err {},
2021-05-30 04:28:24 +02:00
}
2021-05-30 00:52:04 +02:00
}
2021-05-30 04:28:24 +02:00
}
2021-06-01 00:34:09 +02:00
// work around for `BoxError` not implementing `std::error::Error`
//
// This is currently required since tower-http's Compression middleware's body type's
// error only implements error when the inner error type does:
// https://github.com/tower-rs/tower-http/blob/master/tower-http/src/lib.rs#L310
//
// Fixing that is a breaking change to tower-http so we should wait a bit, but should
// totally fix it at some point.
#[derive(Debug, thiserror::Error)]
#[error("{0}")]
pub struct BoxStdError(#[source] tower::BoxError);