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::request::{Envelope, Request, RequestBody};
use crate::response::{Response, ResponseBody};
use crate::server::ServerConfig;
use crate::{BoxFuture, Next, Via, raise};
const MAX_URI_PATH_LEN: usize = 8092;
pub struct FutureResponse(BoxFuture);
pub struct ServiceAdapter<App> {
service: Arc<ViaService<App>>,
}
struct ViaService<App> {
config: Box<ServerConfig>,
via: Via<App>,
}
impl FutureResponse {
fn max_path_len_exceeded() -> Self {
Self(Box::pin(async {
raise!(
414,
message = "path exceeds the maximum allowed length of 8 KB",
);
}))
}
}
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()))
}
}
impl<App> ServiceAdapter<App> {
pub(crate) fn new(config: ServerConfig, via: Via<App>) -> Self {
let config = Box::new(config);
Self {
service: Arc::new(ViaService { config, via }),
}
}
pub(crate) fn config(&self) -> &ServerConfig {
&self.service.config
}
}
impl<App> Clone for ServiceAdapter<App> {
#[inline]
fn clone(&self) -> Self {
Self {
service: Arc::clone(&self.service),
}
}
}
impl<App> Service<http::Request<Incoming>> for ServiceAdapter<App> {
type Error = Infallible;
type Future = FutureResponse;
type Response = http::Response<ResponseBody>;
fn call(&self, request: http::Request<Incoming>) -> Self::Future {
self.service.call(request)
}
}
impl<App> Service<http::Request<Incoming>> for ViaService<App> {
type Error = Infallible;
type Future = FutureResponse;
type Response = http::Response<ResponseBody>;
fn call(&self, request: http::Request<Incoming>) -> Self::Future {
let path = request.uri().path();
if path.len() > MAX_URI_PATH_LEN {
return FutureResponse::max_path_len_exceeded();
}
let mut deque = VecDeque::with_capacity(18);
let mut params = Vec::with_capacity(6);
for (route, param) in self.via.router().traverse(path) {
deque.extend(route);
params.extend(param);
}
let app = self.via.app().clone();
let request = {
let (parts, body) = request.into_parts();
let envelope = Envelope::new(parts, params);
let body = RequestBody::new(body, self.config.max_request_size());
Request::new(envelope, body, app)
};
FutureResponse(Next::new(deque).call(request))
}
}