Files
axum/src/lib.rs
T

1056 lines
28 KiB
Rust
Raw Normal View History

2021-05-29 21:13:06 +02:00
#![allow(unused_imports, dead_code)]
/*
Improvements to make:
2021-05-30 12:26:58 +02:00
Break stuff up into modules
2021-05-29 21:13:06 +02:00
Support extracting headers, perhaps via `headers::Header`?
Tests
*/
use async_trait::async_trait;
use bytes::Bytes;
2021-05-30 00:52:04 +02:00
use futures_util::{future, ready};
2021-05-30 12:26:58 +02:00
use http::{header, HeaderValue, Method, Request, Response, StatusCode};
2021-05-30 04:28:24 +02:00
use http_body::Body as _;
2021-05-30 01:11:18 +02:00
use pin_project::pin_project;
2021-05-29 21:13:06 +02:00
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::{
2021-05-30 02:29:41 +02:00
convert::Infallible,
2021-05-29 21:13:06 +02:00
future::Future,
marker::PhantomData,
2021-05-30 01:11:18 +02:00
pin::Pin,
2021-05-29 21:13:06 +02:00
task::{Context, Poll},
};
2021-05-30 03:10:55 +02:00
use tower::{BoxError, Layer, Service, ServiceExt};
2021-05-29 21:13:06 +02:00
2021-05-30 04:28:24 +02:00
mod body;
pub use body::BoxBody;
2021-05-29 21:13:06 +02:00
pub use hyper::body::Body;
pub fn app() -> App<EmptyRouter> {
App {
router: EmptyRouter(()),
}
}
2021-05-30 00:52:04 +02:00
#[derive(Debug, Clone)]
2021-05-29 21:13:06 +02:00
pub struct App<R> {
router: R,
}
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 00:52:04 +02:00
#[derive(Debug, Clone)]
pub struct RouteAt<R> {
2021-05-29 21:13:06 +02:00
app: App<R>,
route_spec: Bytes,
}
2021-05-30 00:52:04 +02:00
impl<R> RouteAt<R> {
2021-05-30 12:26:58 +02:00
pub fn get<F, B, T>(self, handler_fn: F) -> RouteBuilder<Route<HandlerSvc<F, B, T>, R>>
2021-05-29 21:13:06 +02:00
where
2021-05-30 12:26:58 +02:00
F: Handler<B, T>,
2021-05-29 21:13:06 +02:00
{
self.add_route(handler_fn, Method::GET)
}
2021-05-30 03:10:55 +02:00
pub fn get_service<S, B>(self, service: S) -> RouteBuilder<Route<S, R>>
where
S: Service<Request<Body>, Response = Response<B>> + Clone,
S::Error: Into<BoxError>,
{
self.add_route_service(service, Method::GET)
}
2021-05-30 12:26:58 +02:00
pub fn post<F, B, T>(self, handler_fn: F) -> RouteBuilder<Route<HandlerSvc<F, B, T>, R>>
2021-05-29 21:13:06 +02:00
where
2021-05-30 12:26:58 +02:00
F: Handler<B, T>,
2021-05-29 21:13:06 +02:00
{
self.add_route(handler_fn, Method::POST)
}
2021-05-30 03:10:55 +02:00
pub fn post_service<S, B>(self, service: S) -> RouteBuilder<Route<S, R>>
where
S: Service<Request<Body>, Response = Response<B>> + Clone,
S::Error: Into<BoxError>,
{
self.add_route_service(service, Method::POST)
}
2021-05-30 12:26:58 +02:00
fn add_route<H, B, T>(
self,
handler: H,
method: Method,
) -> RouteBuilder<Route<HandlerSvc<H, B, T>, R>>
2021-05-29 21:13:06 +02:00
where
2021-05-30 12:26:58 +02:00
H: Handler<B, T>,
2021-05-29 21:13:06 +02:00
{
2021-05-30 03:10:55 +02:00
self.add_route_service(HandlerSvc::new(handler), method)
}
fn add_route_service<S>(self, service: S, method: Method) -> RouteBuilder<Route<S, R>> {
2021-05-29 21:13:06 +02:00
let new_app = App {
router: Route {
2021-05-30 03:10:55 +02:00
service,
2021-05-29 21:13:06 +02:00
route_spec: RouteSpec {
method,
spec: self.route_spec.clone(),
},
fallback: self.app.router,
2021-05-30 00:52:04 +02:00
handler_ready: false,
fallback_ready: false,
2021-05-29 21:13:06 +02:00
},
};
RouteBuilder {
app: new_app,
route_spec: self.route_spec,
}
}
}
2021-05-30 00:52:04 +02:00
pub struct RouteBuilder<R> {
app: App<R>,
route_spec: Bytes,
}
2021-05-30 04:28:24 +02:00
impl<R> Clone for RouteBuilder<R>
where
R: Clone,
{
fn clone(&self) -> Self {
Self {
app: self.app.clone(),
route_spec: self.route_spec.clone(),
}
}
}
2021-05-30 00:52:04 +02:00
impl<R> RouteBuilder<R> {
pub fn at(self, route_spec: &str) -> RouteAt<R> {
self.app.at(route_spec)
}
2021-05-30 12:26:58 +02:00
pub fn get<F, B, T>(self, handler_fn: F) -> RouteBuilder<Route<HandlerSvc<F, B, T>, R>>
2021-05-30 00:52:04 +02:00
where
2021-05-30 12:26:58 +02:00
F: Handler<B, T>,
2021-05-30 00:52:04 +02:00
{
self.app.at_bytes(self.route_spec).get(handler_fn)
}
2021-05-30 03:10:55 +02:00
pub fn get_service<S, B>(self, service: S) -> RouteBuilder<Route<S, R>>
where
S: Service<Request<Body>, Response = Response<B>> + Clone,
S::Error: Into<BoxError>,
{
self.app.at_bytes(self.route_spec).get_service(service)
}
2021-05-30 12:26:58 +02:00
pub fn post<F, B, T>(self, handler_fn: F) -> RouteBuilder<Route<HandlerSvc<F, B, T>, R>>
2021-05-30 00:52:04 +02:00
where
2021-05-30 12:26:58 +02:00
F: Handler<B, T>,
2021-05-30 00:52:04 +02:00
{
self.app.at_bytes(self.route_spec).post(handler_fn)
}
2021-05-30 03:10:55 +02:00
pub fn post_service<S, B>(self, service: S) -> RouteBuilder<Route<S, R>>
where
S: Service<Request<Body>, Response = Response<B>> + Clone,
S::Error: Into<BoxError>,
{
self.app.at_bytes(self.route_spec).post_service(service)
}
2021-05-30 04:28:24 +02:00
pub fn into_service(self) -> IntoService<R> {
IntoService {
app: self.app,
poll_ready_error: None,
}
}
2021-05-30 00:52:04 +02:00
}
2021-05-29 21:13:06 +02:00
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
2021-05-30 00:52:04 +02:00
pub enum Error {
#[error("failed to deserialize the request body")]
DeserializeRequestBody(#[source] serde_json::Error),
2021-05-30 12:26:58 +02:00
#[error("failed to serialize the response body")]
SerializeResponseBody(#[source] serde_json::Error),
2021-05-30 00:52:04 +02:00
#[error("failed to consume the body")]
2021-05-30 04:28:24 +02:00
ConsumeRequestBody(#[source] hyper::Error),
2021-05-30 00:52:04 +02:00
#[error("URI contained no query string")]
QueryStringMissing,
#[error("failed to deserialize query string")]
2021-05-30 04:28:24 +02:00
DeserializeQueryString(#[source] serde_urlencoded::de::Error),
2021-05-30 01:56:52 +02:00
#[error("failed generating the response body")]
ResponseBody(#[source] BoxError),
2021-05-30 03:10:55 +02:00
#[error("handler service returned an error")]
Service(#[source] BoxError),
2021-05-30 11:07:56 +02:00
2021-05-30 12:30:52 +02:00
#[error("request extension of type `{type_name}` was not set")]
2021-05-30 11:07:56 +02:00
MissingExtension { type_name: &'static str },
2021-05-30 03:10:55 +02:00
}
2021-05-30 02:29:41 +02:00
impl From<Infallible> for Error {
fn from(err: Infallible) -> Self {
match err {}
}
}
2021-05-30 11:19:36 +02:00
mod sealed {
pub trait HiddentTrait {}
pub struct Hidden;
impl HiddentTrait for Hidden {}
}
2021-05-29 21:13:06 +02:00
#[async_trait]
2021-05-30 12:26:58 +02:00
pub trait Handler<B, In>: Sized {
type Response: IntoResponse<B>;
2021-05-30 01:35:17 +02:00
2021-05-30 11:19:36 +02:00
// This seals the trait. We cannot use the regular "sealed super trait" approach
// due to coherence.
#[doc(hidden)]
type Sealed: sealed::HiddentTrait;
2021-05-30 11:56:13 +02:00
async fn call(self, req: Request<Body>) -> Result<Self::Response, Error>;
2021-05-30 03:10:55 +02:00
fn layer<L>(self, layer: L) -> Layered<L::Service, In>
where
2021-05-30 12:26:58 +02:00
L: Layer<HandlerSvc<Self, B, In>>,
2021-05-30 03:10:55 +02:00
{
Layered::new(layer.layer(HandlerSvc::new(self)))
}
2021-05-29 21:13:06 +02:00
}
2021-05-30 12:26:58 +02:00
pub trait IntoResponse<B> {
fn into_response(self) -> Result<Response<B>, Error>;
2021-05-30 11:56:13 +02:00
}
2021-05-30 12:26:58 +02:00
impl<B> IntoResponse<B> for Response<B> {
fn into_response(self) -> Result<Response<B>, Error> {
Ok(self)
}
}
impl IntoResponse<Body> for &'static str {
fn into_response(self) -> Result<Response<Body>, Error> {
Ok(Response::new(Body::from(self)))
}
}
impl IntoResponse<Body> for String {
fn into_response(self) -> Result<Response<Body>, Error> {
Ok(Response::new(Body::from(self)))
}
}
impl IntoResponse<Body> for Bytes {
fn into_response(self) -> Result<Response<Body>, Error> {
Ok(Response::new(Body::from(self)))
}
}
impl IntoResponse<Body> for &'static [u8] {
fn into_response(self) -> Result<Response<Body>, Error> {
Ok(Response::new(Body::from(self)))
2021-05-30 11:56:13 +02:00
}
}
2021-05-30 12:26:58 +02:00
impl IntoResponse<Body> for Vec<u8> {
fn into_response(self) -> Result<Response<Body>, Error> {
Ok(Response::new(Body::from(self)))
}
}
impl IntoResponse<Body> for std::borrow::Cow<'static, str> {
fn into_response(self) -> Result<Response<Body>, Error> {
Ok(Response::new(Body::from(self)))
}
}
impl IntoResponse<Body> for std::borrow::Cow<'static, [u8]> {
fn into_response(self) -> Result<Response<Body>, Error> {
Ok(Response::new(Body::from(self)))
}
}
// TODO(david): rename this to Json when its in another module
pub struct JsonBody<T>(T);
impl<T> IntoResponse<Body> for JsonBody<T>
where
T: Serialize,
{
fn into_response(self) -> Result<Response<Body>, Error> {
let bytes = serde_json::to_vec(&self.0).map_err(Error::SerializeResponseBody)?;
let len = bytes.len();
let mut res = Response::new(Body::from(bytes));
res.headers_mut().insert(
header::CONTENT_TYPE,
HeaderValue::from_static("application/json"),
);
res.headers_mut()
.insert(header::CONTENT_LENGTH, HeaderValue::from(len));
Ok(res)
2021-05-30 11:56:13 +02:00
}
}
2021-05-29 21:13:06 +02:00
#[async_trait]
2021-05-30 12:26:58 +02:00
impl<F, Fut, B, Res> Handler<B, ()> for F
2021-05-29 21:13:06 +02:00
where
F: Fn(Request<Body>) -> Fut + Send + Sync,
2021-05-30 11:56:13 +02:00
Fut: Future<Output = Result<Res, Error>> + Send,
2021-05-30 12:26:58 +02:00
Res: IntoResponse<B>,
2021-05-29 21:13:06 +02:00
{
2021-05-30 11:56:13 +02:00
type Response = Res;
2021-05-30 01:35:17 +02:00
2021-05-30 11:19:36 +02:00
type Sealed = sealed::Hidden;
2021-05-30 11:56:13 +02:00
async fn call(self, req: Request<Body>) -> Result<Self::Response, Error> {
2021-05-30 01:11:18 +02:00
self(req).await
2021-05-29 21:13:06 +02:00
}
}
2021-05-30 00:52:04 +02:00
macro_rules! impl_handler {
( $head:ident $(,)? ) => {
#[async_trait]
#[allow(non_snake_case)]
2021-05-30 12:26:58 +02:00
impl<F, Fut, B, Res, $head> Handler<B, ($head,)> for F
2021-05-30 00:52:04 +02:00
where
F: Fn(Request<Body>, $head) -> Fut + Send + Sync,
2021-05-30 11:56:13 +02:00
Fut: Future<Output = Result<Res, Error>> + Send,
2021-05-30 12:26:58 +02:00
Res: IntoResponse<B>,
2021-05-30 00:52:04 +02:00
$head: FromRequest + Send,
{
2021-05-30 11:56:13 +02:00
type Response = Res;
2021-05-30 01:35:17 +02:00
2021-05-30 11:19:36 +02:00
type Sealed = sealed::Hidden;
2021-05-30 11:56:13 +02:00
async fn call(self, mut req: Request<Body>) -> Result<Self::Response, Error> {
2021-05-30 00:52:04 +02:00
let $head = $head::from_request(&mut req).await?;
let res = self(req, $head).await?;
Ok(res)
}
}
};
( $head:ident, $($tail:ident),* $(,)? ) => {
#[async_trait]
#[allow(non_snake_case)]
2021-05-30 12:26:58 +02:00
impl<F, Fut, B, Res, $head, $($tail,)*> Handler<B, ($head, $($tail,)*)> for F
2021-05-30 00:52:04 +02:00
where
F: Fn(Request<Body>, $head, $($tail,)*) -> Fut + Send + Sync,
2021-05-30 11:56:13 +02:00
Fut: Future<Output = Result<Res, Error>> + Send,
2021-05-30 12:26:58 +02:00
Res: IntoResponse<B>,
2021-05-30 00:52:04 +02:00
$head: FromRequest + Send,
$( $tail: FromRequest + Send, )*
{
2021-05-30 11:56:13 +02:00
type Response = Res;
2021-05-30 01:35:17 +02:00
2021-05-30 11:19:36 +02:00
type Sealed = sealed::Hidden;
2021-05-30 11:56:13 +02:00
async fn call(self, mut req: Request<Body>) -> Result<Self::Response, Error> {
2021-05-30 00:52:04 +02:00
let $head = $head::from_request(&mut req).await?;
$(
let $tail = $tail::from_request(&mut req).await?;
)*
let res = self(req, $head, $($tail,)*).await?;
Ok(res)
}
}
2021-05-29 21:13:06 +02:00
2021-05-30 00:52:04 +02:00
impl_handler!($($tail,)*);
};
2021-05-29 21:13:06 +02:00
}
2021-05-30 00:52:04 +02:00
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
2021-05-30 03:10:55 +02:00
pub struct Layered<S, T> {
svc: S,
_input: PhantomData<fn() -> T>,
}
impl<S, T> Clone for Layered<S, T>
where
S: Clone,
{
fn clone(&self) -> Self {
Self::new(self.svc.clone())
}
}
#[async_trait]
2021-05-30 12:26:58 +02:00
impl<S, B, T> Handler<B, T> for Layered<S, T>
2021-05-30 03:10:55 +02:00
where
2021-05-30 12:26:58 +02:00
S: Service<Request<Body>, Response = Response<B>> + Send,
2021-05-30 03:10:55 +02:00
S::Error: Into<BoxError>,
S::Future: Send,
{
2021-05-30 11:56:13 +02:00
type Response = S::Response;
2021-05-30 03:10:55 +02:00
2021-05-30 11:19:36 +02:00
type Sealed = sealed::Hidden;
2021-05-30 11:56:13 +02:00
async fn call(self, req: Request<Body>) -> Result<Self::Response, Error> {
2021-05-30 03:10:55 +02:00
self.svc
.oneshot(req)
.await
2021-05-30 04:28:24 +02:00
.map_err(|err| Error::Service(err.into()))
2021-05-30 03:10:55 +02:00
}
}
impl<S, T> Layered<S, T> {
fn new(svc: S) -> Self {
Self {
svc,
_input: PhantomData,
}
}
}
2021-05-30 12:26:58 +02:00
pub struct HandlerSvc<H, B, T> {
2021-05-29 21:13:06 +02:00
handler: H,
2021-05-30 12:26:58 +02:00
_input: PhantomData<fn() -> (B, T)>,
2021-05-29 21:13:06 +02:00
}
2021-05-30 12:26:58 +02:00
impl<H, B, T> HandlerSvc<H, B, T> {
2021-05-30 03:10:55 +02:00
fn new(handler: H) -> Self {
Self {
handler,
_input: PhantomData,
}
}
}
2021-05-30 12:26:58 +02:00
impl<H, B, T> Clone for HandlerSvc<H, B, T>
2021-05-29 21:13:06 +02:00
where
H: Clone,
{
fn clone(&self) -> Self {
Self {
handler: self.handler.clone(),
_input: PhantomData,
}
}
}
2021-05-30 12:26:58 +02:00
impl<H, B, T> Service<Request<Body>> for HandlerSvc<H, B, T>
2021-05-29 21:13:06 +02:00
where
2021-05-30 12:26:58 +02:00
H: Handler<B, T> + Clone + Send + 'static,
2021-05-30 11:56:13 +02:00
H::Response: 'static,
2021-05-29 21:13:06 +02:00
{
2021-05-30 12:26:58 +02:00
type Response = Response<B>;
2021-05-29 21:13:06 +02:00
type Error = Error;
type Future = future::BoxFuture<'static, Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
2021-05-30 12:26:58 +02:00
// HandlerSvc can only be constructed from async functions which are always ready, or from
// `Layered` which bufferes in `<Layered as Handler>::call` and is therefore also always
// ready.
2021-05-29 21:13:06 +02:00
Poll::Ready(Ok(()))
}
fn call(&mut self, req: Request<Body>) -> Self::Future {
let handler = self.handler.clone();
2021-05-30 11:56:13 +02:00
Box::pin(async move {
2021-05-30 12:26:58 +02:00
let res = Handler::call(handler, req).await?.into_response()?;
Ok(res)
2021-05-30 11:56:13 +02:00
})
2021-05-29 21:13:06 +02:00
}
}
pub trait FromRequest: Sized {
2021-05-30 01:11:18 +02:00
type Future: Future<Output = Result<Self, Error>> + Send;
fn from_request(req: &mut Request<Body>) -> Self::Future;
2021-05-30 00:52:04 +02:00
}
impl<T> FromRequest for Option<T>
where
T: FromRequest,
{
2021-05-30 01:11:18 +02:00
type Future = OptionFromRequestFuture<T::Future>;
fn from_request(req: &mut Request<Body>) -> Self::Future {
OptionFromRequestFuture(T::from_request(req))
}
}
#[pin_project]
pub struct OptionFromRequestFuture<F>(#[pin] F);
impl<F, T> Future for OptionFromRequestFuture<F>
where
F: Future<Output = Result<T, Error>>,
{
type Output = Result<Option<T>, Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let value = ready!(self.project().0.poll(cx));
Poll::Ready(Ok(value.ok()))
2021-05-30 00:52:04 +02:00
}
2021-05-29 21:13:06 +02:00
}
2021-05-30 00:52:04 +02:00
#[derive(Debug, Clone, Copy)]
pub struct Query<T>(T);
2021-05-29 21:13:06 +02:00
impl<T> Query<T> {
2021-05-30 00:52:04 +02:00
pub fn into_inner(self) -> T {
2021-05-29 21:13:06 +02:00
self.0
}
}
impl<T> FromRequest for Query<T>
where
2021-05-30 01:11:18 +02:00
T: DeserializeOwned + Send,
2021-05-29 21:13:06 +02:00
{
2021-05-30 01:11:18 +02:00
type Future = future::Ready<Result<Self, Error>>;
fn from_request(req: &mut Request<Body>) -> Self::Future {
let result = (|| {
let query = req.uri().query().ok_or(Error::QueryStringMissing)?;
2021-05-30 04:28:24 +02:00
let value = serde_urlencoded::from_str(query).map_err(Error::DeserializeQueryString)?;
2021-05-30 01:11:18 +02:00
Ok(Query(value))
})();
future::ready(result)
2021-05-29 21:13:06 +02:00
}
}
2021-05-30 00:52:04 +02:00
#[derive(Debug, Clone, Copy)]
pub struct Json<T>(T);
2021-05-29 21:13:06 +02:00
impl<T> Json<T> {
2021-05-30 00:52:04 +02:00
pub fn into_inner(self) -> T {
2021-05-29 21:13:06 +02:00
self.0
}
}
impl<T> FromRequest for Json<T>
where
T: DeserializeOwned,
{
2021-05-30 01:11:18 +02:00
type Future = future::BoxFuture<'static, Result<Self, Error>>;
fn from_request(req: &mut Request<Body>) -> Self::Future {
2021-05-29 21:13:06 +02:00
// TODO(david): require the body to have `content-type: application/json`
let body = std::mem::take(req.body_mut());
2021-05-30 01:11:18 +02:00
Box::pin(async move {
let bytes = hyper::body::to_bytes(body)
.await
2021-05-30 04:28:24 +02:00
.map_err(Error::ConsumeRequestBody)?;
2021-05-30 01:11:18 +02:00
let value = serde_json::from_slice(&bytes).map_err(Error::DeserializeRequestBody)?;
Ok(Json(value))
})
2021-05-29 21:13:06 +02:00
}
}
2021-05-30 11:07:56 +02:00
#[derive(Debug, Clone, Copy)]
pub struct Extension<T>(T);
impl<T> Extension<T> {
pub fn into_inner(self) -> T {
self.0
}
}
impl<T> FromRequest for Extension<T>
where
T: Clone + Send + Sync + 'static,
{
type Future = future::Ready<Result<Self, Error>>;
fn from_request(req: &mut Request<Body>) -> Self::Future {
let result = (|| {
let value = req
.extensions()
.get::<T>()
.ok_or_else(|| Error::MissingExtension {
type_name: std::any::type_name::<T>(),
})
.map(|x| x.clone())?;
Ok(Extension(value))
})();
future::ready(result)
}
}
2021-05-30 12:26:58 +02:00
// TODO(david): rename this to Bytes when its in another module
2021-05-30 12:30:52 +02:00
// TODO(david): can we add a length limit somehow? Maybe a const generic?
2021-05-30 12:26:58 +02:00
#[derive(Debug, Clone)]
pub struct BytesBody(Bytes);
impl BytesBody {
pub fn into_inner(self) -> Bytes {
self.0
}
}
impl FromRequest for BytesBody {
type Future = future::BoxFuture<'static, Result<Self, Error>>;
fn from_request(req: &mut Request<Body>) -> Self::Future {
let body = std::mem::take(req.body_mut());
Box::pin(async move {
let bytes = hyper::body::to_bytes(body)
.await
.map_err(Error::ConsumeRequestBody)?;
Ok(BytesBody(bytes))
})
}
}
2021-05-29 21:13:06 +02:00
#[derive(Clone, Copy)]
pub struct EmptyRouter(());
2021-05-30 00:52:04 +02:00
impl<R> Service<R> for EmptyRouter {
2021-05-29 21:13:06 +02:00
type Response = Response<Body>;
2021-05-30 02:29:41 +02:00
type Error = Infallible;
2021-05-29 21:13:06 +02:00
type Future = future::Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
2021-05-30 00:52:04 +02:00
fn call(&mut self, _req: R) -> Self::Future {
2021-05-29 21:13:06 +02:00
let mut res = Response::new(Body::empty());
*res.status_mut() = StatusCode::NOT_FOUND;
2021-05-30 01:11:18 +02:00
future::ok(res)
2021-05-29 21:13:06 +02:00
}
}
pub struct Route<H, F> {
2021-05-30 03:10:55 +02:00
service: H,
2021-05-29 21:13:06 +02:00
route_spec: RouteSpec,
fallback: F,
2021-05-30 00:52:04 +02:00
handler_ready: bool,
fallback_ready: bool,
2021-05-29 21:13:06 +02:00
}
2021-05-30 01:11:18 +02:00
impl<H, F> Clone for Route<H, F>
where
H: Clone,
F: Clone,
{
fn clone(&self) -> Self {
Self {
2021-05-30 03:10:55 +02:00
service: self.service.clone(),
2021-05-30 01:11:18 +02:00
fallback: self.fallback.clone(),
route_spec: self.route_spec.clone(),
// important to reset readiness when cloning
handler_ready: false,
fallback_ready: false,
}
}
}
2021-05-29 21:13:06 +02:00
#[derive(Clone)]
struct RouteSpec {
method: Method,
spec: Bytes,
}
impl RouteSpec {
fn matches<B>(&self, req: &Request<B>) -> bool {
// TODO(david): support dynamic placeholders like `/users/:id`
req.method() == self.method && req.uri().path().as_bytes() == self.spec
}
}
2021-05-30 01:56:52 +02:00
impl<H, F, HB, FB> Service<Request<Body>> for Route<H, F>
2021-05-29 21:13:06 +02:00
where
2021-05-30 02:29:41 +02:00
H: Service<Request<Body>, Response = Response<HB>>,
H::Error: Into<Error>,
2021-05-30 01:56:52 +02:00
HB: http_body::Body + Send + Sync + 'static,
HB::Error: Into<BoxError>,
2021-05-30 02:29:41 +02:00
F: Service<Request<Body>, Response = Response<FB>>,
F::Error: Into<Error>,
2021-05-30 01:56:52 +02:00
FB: http_body::Body<Data = HB::Data> + Send + Sync + 'static,
FB::Error: Into<BoxError>,
2021-05-29 21:13:06 +02:00
{
2021-05-30 01:56:52 +02:00
type Response = Response<BoxBody<HB::Data, Error>>;
2021-05-29 21:13:06 +02:00
type Error = Error;
2021-05-30 01:56:52 +02:00
type Future = future::Either<BoxResponseBody<H::Future>, BoxResponseBody<F::Future>>;
2021-05-30 00:52:04 +02:00
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
2021-05-30 01:11:18 +02:00
loop {
if !self.handler_ready {
2021-05-30 03:10:55 +02:00
ready!(self.service.poll_ready(cx)).map_err(Into::into)?;
2021-05-30 01:11:18 +02:00
self.handler_ready = true;
}
2021-05-30 00:52:04 +02:00
2021-05-30 01:11:18 +02:00
if !self.fallback_ready {
2021-05-30 02:29:41 +02:00
ready!(self.fallback.poll_ready(cx)).map_err(Into::into)?;
2021-05-30 01:11:18 +02:00
self.fallback_ready = true;
}
2021-05-29 21:13:06 +02:00
2021-05-30 01:11:18 +02:00
if self.handler_ready && self.fallback_ready {
return Poll::Ready(Ok(()));
}
}
2021-05-29 21:13:06 +02:00
}
fn call(&mut self, req: Request<Body>) -> Self::Future {
if self.route_spec.matches(&req) {
2021-05-30 01:11:18 +02:00
assert!(
self.handler_ready,
"handler not ready. Did you forget to call `poll_ready`?"
);
2021-05-30 00:52:04 +02:00
self.handler_ready = false;
2021-05-30 03:10:55 +02:00
future::Either::Left(BoxResponseBody(self.service.call(req)))
2021-05-29 21:13:06 +02:00
} else {
2021-05-30 01:11:18 +02:00
assert!(
self.fallback_ready,
"fallback not ready. Did you forget to call `poll_ready`?"
);
2021-05-30 00:52:04 +02:00
self.fallback_ready = false;
2021-05-30 01:56:52 +02:00
// TODO(david): this leads to each route creating one box body, probably not great
future::Either::Right(BoxResponseBody(self.fallback.call(req)))
2021-05-29 21:13:06 +02:00
}
}
}
2021-05-30 01:56:52 +02:00
#[pin_project]
pub struct BoxResponseBody<F>(#[pin] F);
2021-05-30 02:29:41 +02:00
impl<F, B, E> Future for BoxResponseBody<F>
2021-05-30 01:56:52 +02:00
where
2021-05-30 02:29:41 +02:00
F: Future<Output = Result<Response<B>, E>>,
E: Into<Error>,
2021-05-30 01:56:52 +02:00
B: http_body::Body + Send + Sync + 'static,
B::Error: Into<BoxError>,
{
type Output = Result<Response<BoxBody<B::Data, Error>>, Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
2021-05-30 02:29:41 +02:00
let response: Response<B> = ready!(self.project().0.poll(cx)).map_err(Into::into)?;
2021-05-30 04:28:24 +02:00
let response = response.map(|body| {
2021-05-30 12:30:52 +02:00
// TODO(david): attempt to downcast this into `Error`
2021-05-30 04:28:24 +02:00
let body = body.map_err(|err| Error::ResponseBody(err.into()));
BoxBody::new(body)
});
2021-05-30 01:56:52 +02:00
Poll::Ready(Ok(response))
}
}
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-30 04:28:24 +02:00
self.app.router.poll_ready(cx).map_err(Into::into)
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() {
match handle_error::<B>(poll_ready_error) {
Ok(res) => {
return HandleErrorFuture(Kind::Response(Some(res)));
}
Err(err) => {
return HandleErrorFuture(Kind::Error(Some(err)));
}
}
}
HandleErrorFuture(Kind::Future(self.app.router.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)),
Err(err) => Poll::Ready(handle_error(err.into())),
},
}
2021-05-30 00:52:04 +02:00
}
2021-05-30 04:28:24 +02:00
}
2021-05-30 00:52:04 +02:00
2021-05-30 04:28:24 +02:00
fn handle_error<B>(error: Error) -> Result<Response<B>, Error>
where
B: Default,
{
fn make_response<B>(status: StatusCode) -> Result<Response<B>, Error>
where
B: Default,
{
let mut res = Response::new(B::default());
*res.status_mut() = status;
Ok(res)
}
match error {
Error::DeserializeRequestBody(_)
| Error::QueryStringMissing
| Error::DeserializeQueryString(_) => make_response(StatusCode::BAD_REQUEST),
2021-05-30 12:26:58 +02:00
Error::MissingExtension { .. } | Error::SerializeResponseBody(_) => {
make_response(StatusCode::INTERNAL_SERVER_ERROR)
}
2021-05-30 11:07:56 +02:00
2021-05-30 04:28:24 +02:00
Error::Service(err) => match err.downcast::<Error>() {
Ok(err) => Err(*err),
Err(err) => Err(Error::Service(err)),
},
err @ Error::ConsumeRequestBody(_) => Err(err),
err @ Error::ResponseBody(_) => Err(err),
2021-05-30 00:52:04 +02:00
}
}
2021-05-29 21:13:06 +02:00
#[cfg(test)]
mod tests {
#![allow(warnings)]
use super::*;
2021-05-30 01:56:52 +02:00
use hyper::Server;
2021-05-30 03:10:55 +02:00
use std::time::Duration;
2021-05-30 11:07:56 +02:00
use std::{fmt, net::SocketAddr, sync::Arc};
2021-05-30 03:10:55 +02:00
use tower::{
layer::util::Identity, make::Shared, service_fn, timeout::TimeoutLayer, ServiceBuilder,
};
2021-05-30 04:28:24 +02:00
use tower_http::{
2021-05-30 11:07:56 +02:00
add_extension::AddExtensionLayer,
2021-05-30 04:28:24 +02:00
compression::CompressionLayer,
trace::{Trace, TraceLayer},
};
2021-05-29 21:13:06 +02:00
#[tokio::test]
async fn basic() {
2021-05-30 02:29:41 +02:00
#[derive(Debug, Deserialize)]
struct Pagination {
page: usize,
per_page: usize,
}
#[derive(Debug, Deserialize)]
struct UsersCreate {
username: String,
}
2021-05-30 03:10:55 +02:00
async fn root(_: Request<Body>) -> Result<Response<Body>, Error> {
Ok(Response::new(Body::from("Hello, World!")))
}
2021-05-30 04:28:24 +02:00
async fn large_static_file(_: Request<Body>) -> Result<Response<Body>, Error> {
Ok(Response::new(Body::empty()))
}
2021-05-30 12:26:58 +02:00
let app =
app()
// routes with functions
.at("/")
.get(root)
// routes with closures
.at("/users")
.get(|_: Request<Body>, pagination: Query<Pagination>| async {
let pagination = pagination.into_inner();
assert_eq!(pagination.page, 1);
assert_eq!(pagination.per_page, 30);
Ok::<_, Error>("users#index".to_string())
})
.post(
|_: Request<Body>,
payload: Json<UsersCreate>,
_state: Extension<Arc<State>>| async {
let payload = payload.into_inner();
assert_eq!(payload.username, "bob");
Ok::<_, Error>(JsonBody(
serde_json::json!({ "username": payload.username }),
))
},
)
// routes with a service
.at("/service")
.get_service(service_fn(root))
// routes with layers applied
.at("/large-static-file")
.get(
large_static_file.layer(
ServiceBuilder::new()
.layer(TimeoutLayer::new(Duration::from_secs(30)))
.layer(CompressionLayer::new())
.into_inner(),
),
)
.into_service();
2021-05-30 11:07:56 +02:00
// state shared by all routes, could hold db connection etc
struct State {}
let state = Arc::new(State {});
2021-05-30 04:28:24 +02:00
// can add more middleware
2021-05-30 11:07:56 +02:00
let mut app = ServiceBuilder::new()
.layer(AddExtensionLayer::new(state))
.layer(TraceLayer::new_for_http())
.service(app);
2021-05-30 02:29:41 +02:00
let res = app
.ready()
.await
.unwrap()
.call(
Request::builder()
.method(Method::GET)
.uri("/")
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(body_to_string(res).await, "Hello, World!");
let res = app
.ready()
.await
.unwrap()
.call(
Request::builder()
.method(Method::GET)
.uri("/users?page=1&per_page=30")
.body(Body::empty())
.unwrap(),
)
.await
2021-05-29 21:13:06 +02:00
.unwrap();
2021-05-30 02:29:41 +02:00
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(body_to_string(res).await, "users#index");
2021-05-30 04:28:24 +02:00
let res = app
.ready()
.await
.unwrap()
.call(
Request::builder()
.method(Method::GET)
.uri("/users")
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
assert_eq!(body_to_string(res).await, "");
2021-05-30 02:29:41 +02:00
let res = app
.ready()
.await
.unwrap()
.call(
Request::builder()
.method(Method::POST)
.uri("/users")
.body(Body::from(r#"{ "username": "bob" }"#))
.unwrap(),
)
.await
.unwrap();
assert_eq!(res.status(), StatusCode::OK);
2021-05-30 12:26:58 +02:00
assert_eq!(body_to_string(res).await, r#"{"username":"bob"}"#);
2021-05-30 02:29:41 +02:00
}
2021-05-29 21:13:06 +02:00
2021-05-30 02:29:41 +02:00
async fn body_to_string<B>(res: Response<B>) -> String
where
B: http_body::Body,
B::Error: fmt::Debug,
{
let bytes = hyper::body::to_bytes(res.into_body()).await.unwrap();
String::from_utf8(bytes.to_vec()).unwrap()
2021-05-29 21:13:06 +02:00
}
2021-05-30 01:56:52 +02:00
#[allow(dead_code)]
// this should just compile
async fn compatible_with_hyper_and_tower_http() {
2021-05-30 04:28:24 +02:00
let app = app()
.at("/")
.get(|_: Request<Body>| async {
Ok::<_, Error>(Response::new(Body::from("Hello, World!")))
})
.into_service();
2021-05-30 01:56:52 +02:00
let app = ServiceBuilder::new()
.layer(TraceLayer::new_for_http())
2021-05-30 04:28:24 +02:00
.layer(CompressionLayer::new())
2021-05-30 01:56:52 +02:00
.service(app);
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let server = Server::bind(&addr).serve(Shared::new(app));
server.await.unwrap();
}
2021-05-29 21:13:06 +02:00
}