use hyper::body::Incoming;
use std::convert::Infallible;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use crate::body::{AnyBody, ByteBuffer};
use crate::middleware::BoxFuture;
use crate::request::{Request, RequestBody};
use crate::router::Router;
use crate::{Error, Response};
type HttpRequest = http::Request<Incoming>;
type HttpResponse = http::Response<AnyBody<ByteBuffer>>;
pub struct FutureResponse {
future: BoxFuture<Result<Response, Error>>,
}
pub struct Service<State> {
router: Arc<Router<State>>,
state: Arc<State>,
}
impl Future for FutureResponse {
type Output = Result<HttpResponse, Infallible>;
fn poll(mut self: Pin<&mut Self>, context: &mut Context) -> Poll<Self::Output> {
self.future
.as_mut()
.poll(context)
.map(|result| match result {
Ok(response) => Ok(response.into_outgoing_response()),
Err(error) => Ok(error.into_response().into_outgoing_response()),
})
}
}
impl<State> Service<State> {
pub fn new(router: Arc<Router<State>>, state: Arc<State>) -> Self {
Self { router, state }
}
}
impl<State> hyper::service::Service<HttpRequest> for Service<State>
where
State: Send + Sync + 'static,
{
type Error = Infallible;
type Future = FutureResponse;
type Response = HttpResponse;
fn call(&self, incoming: HttpRequest) -> Self::Future {
let mut request = {
let (parts, body) = incoming.into_parts();
let parts = Box::new(parts);
let body = RequestBody::new(AnyBody::Inline(body));
let state = Arc::clone(&self.state);
Request::new(parts, body, state)
};
let next = {
let path = request.parts.uri.path();
let params = &mut request.params;
self.router.lookup(path, params)
};
Self::Future {
future: next.call(request),
}
}
}