use http::request::Parts;
use hyper::body::Incoming;
use hyper::service::Service;
use std::collections::VecDeque;
use std::convert::Infallible;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use crate::middleware::BoxFuture;
use crate::request::{Envelope, Request};
use crate::response::{Response, ResponseBody};
use crate::{Next, Via};
pub struct FutureResponse(BoxFuture);
pub struct AppService<App> {
app: Arc<Via<App>>,
max_request_size: usize,
}
impl<App> AppService<App> {
#[inline]
pub(crate) fn new(app: Arc<Via<App>>, max_request_size: usize) -> Self {
Self {
app,
max_request_size,
}
}
}
impl<App> Clone for AppService<App> {
#[inline]
fn clone(&self) -> Self {
Self {
app: Arc::clone(&self.app),
max_request_size: self.max_request_size,
}
}
}
impl<App> Service<http::Request<Incoming>> for AppService<App> {
type Error = Infallible;
type Future = FutureResponse;
type Response = http::Response<ResponseBody>;
fn call(&self, request: http::Request<Incoming>) -> Self::Future {
let mut deque = VecDeque::new();
let mut request = {
let params = Vec::with_capacity(6);
let app = self.app.app.clone();
Request::new(app, self.max_request_size, params, request)
};
let Envelope {
ref mut params,
parts: Parts { ref uri, .. },
..
} = *request.envelope_mut();
for (route, param) in self.app.router.traverse(uri.path()) {
deque.extend(route.cloned());
if let Some((name, range)) = param {
params.push((name.clone(), range));
}
}
FutureResponse(Next::new(deque).call(request))
}
}
impl Future for FutureResponse {
type Output = Result<http::Response<ResponseBody>, Infallible>;
fn poll(mut self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Self::Output> {
self.0
.as_mut()
.poll(context)
.map(|result| Ok(result.unwrap_or_else(Response::from).into()))
}
}