1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2025-01-20 14:08:07 +00:00
actix-web/actix-framed/src/app.rs

222 lines
6.3 KiB
Rust
Raw Normal View History

2019-11-21 06:17:01 +00:00
use std::future::Future;
use std::pin::Pin;
2019-04-10 22:06:27 +00:00
use std::rc::Rc;
2019-11-21 06:17:01 +00:00
use std::task::{Context, Poll};
2019-04-10 22:06:27 +00:00
use actix_codec::{AsyncRead, AsyncWrite, Framed};
use actix_http::h1::{Codec, SendResponse};
use actix_http::{Error, Request, Response};
use actix_router::{Path, Router, Url};
2019-11-21 06:17:01 +00:00
use actix_service::{IntoServiceFactory, Service, ServiceFactory};
use futures_util::future::{ok, FutureExt, LocalBoxFuture};
2019-04-10 22:06:27 +00:00
use crate::helpers::{BoxedHttpNewService, BoxedHttpService, HttpNewService};
use crate::request::FramedRequest;
use crate::state::State;
2019-11-21 06:17:01 +00:00
type BoxedResponse = LocalBoxFuture<'static, Result<(), Error>>;
2019-04-10 22:06:27 +00:00
pub trait HttpServiceFactory {
2019-11-21 06:17:01 +00:00
type Factory: ServiceFactory;
2019-04-10 22:06:27 +00:00
fn path(&self) -> &str;
fn create(self) -> Self::Factory;
}
/// Application builder
2019-04-11 01:08:28 +00:00
pub struct FramedApp<T, S = ()> {
2019-04-10 22:06:27 +00:00
state: State<S>,
services: Vec<(String, BoxedHttpNewService<FramedRequest<T, S>>)>,
}
2019-04-11 01:08:28 +00:00
impl<T: 'static> FramedApp<T, ()> {
2019-04-10 22:06:27 +00:00
pub fn new() -> Self {
2019-04-11 01:08:28 +00:00
FramedApp {
2019-04-10 22:06:27 +00:00
state: State::new(()),
services: Vec::new(),
}
}
}
2019-04-11 01:08:28 +00:00
impl<T: 'static, S: 'static> FramedApp<T, S> {
pub fn with(state: S) -> FramedApp<T, S> {
FramedApp {
2019-04-10 22:06:27 +00:00
services: Vec::new(),
state: State::new(state),
}
}
pub fn service<U>(mut self, factory: U) -> Self
where
U: HttpServiceFactory,
2019-11-21 06:17:01 +00:00
U::Factory: ServiceFactory<
2019-05-12 15:34:51 +00:00
Config = (),
2019-04-10 22:06:27 +00:00
Request = FramedRequest<T, S>,
Response = (),
Error = Error,
InitError = (),
> + 'static,
2019-11-21 06:17:01 +00:00
<U::Factory as ServiceFactory>::Future: 'static,
<U::Factory as ServiceFactory>::Service: Service<
2019-04-10 22:06:27 +00:00
Request = FramedRequest<T, S>,
Response = (),
Error = Error,
2019-11-21 06:17:01 +00:00
Future = LocalBoxFuture<'static, Result<(), Error>>,
2019-04-10 22:06:27 +00:00
>,
{
let path = factory.path().to_string();
self.services
.push((path, Box::new(HttpNewService::new(factory.create()))));
self
}
}
2019-11-21 06:17:01 +00:00
impl<T, S> IntoServiceFactory<FramedAppFactory<T, S>> for FramedApp<T, S>
2019-04-10 22:06:27 +00:00
where
2019-11-21 06:17:01 +00:00
T: AsyncRead + AsyncWrite + Unpin + 'static,
2019-04-10 22:06:27 +00:00
S: 'static,
{
2019-11-21 06:17:01 +00:00
fn into_factory(self) -> FramedAppFactory<T, S> {
2019-04-11 01:08:28 +00:00
FramedAppFactory {
2019-04-10 22:06:27 +00:00
state: self.state,
services: Rc::new(self.services),
}
}
}
#[derive(Clone)]
2019-04-11 01:08:28 +00:00
pub struct FramedAppFactory<T, S> {
2019-04-10 22:06:27 +00:00
state: State<S>,
services: Rc<Vec<(String, BoxedHttpNewService<FramedRequest<T, S>>)>>,
}
2019-11-21 06:17:01 +00:00
impl<T, S> ServiceFactory for FramedAppFactory<T, S>
2019-04-10 22:06:27 +00:00
where
2019-11-21 06:17:01 +00:00
T: AsyncRead + AsyncWrite + Unpin + 'static,
2019-04-10 22:06:27 +00:00
S: 'static,
{
2019-12-02 11:33:11 +00:00
type Config = ();
2019-04-10 22:06:27 +00:00
type Request = (Request, Framed<T, Codec>);
type Response = ();
type Error = Error;
type InitError = ();
2019-07-20 04:50:36 +00:00
type Service = FramedAppService<T, S>;
2019-04-10 22:06:27 +00:00
type Future = CreateService<T, S>;
2019-12-02 15:37:13 +00:00
fn new_service(&self, _: ()) -> Self::Future {
2019-04-10 22:06:27 +00:00
CreateService {
fut: self
.services
.iter()
.map(|(path, service)| {
CreateServiceItem::Future(
Some(path.clone()),
2019-12-02 15:37:13 +00:00
service.new_service(()),
2019-04-10 22:06:27 +00:00
)
})
.collect(),
state: self.state.clone(),
}
}
}
#[doc(hidden)]
pub struct CreateService<T, S> {
fut: Vec<CreateServiceItem<T, S>>,
state: State<S>,
}
enum CreateServiceItem<T, S> {
Future(
Option<String>,
2019-11-21 06:17:01 +00:00
LocalBoxFuture<'static, Result<BoxedHttpService<FramedRequest<T, S>>, ()>>,
2019-04-10 22:06:27 +00:00
),
Service(String, BoxedHttpService<FramedRequest<T, S>>),
}
impl<S: 'static, T: 'static> Future for CreateService<T, S>
where
2019-11-21 06:17:01 +00:00
T: AsyncRead + AsyncWrite + Unpin,
2019-04-10 22:06:27 +00:00
{
2019-11-21 06:17:01 +00:00
type Output = Result<FramedAppService<T, S>, ()>;
2019-04-10 22:06:27 +00:00
2019-11-21 06:17:01 +00:00
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
2019-04-10 22:06:27 +00:00
let mut done = true;
// poll http services
for item in &mut self.fut {
let res = match item {
CreateServiceItem::Future(ref mut path, ref mut fut) => {
2019-11-21 06:17:01 +00:00
match Pin::new(fut).poll(cx) {
Poll::Ready(Ok(service)) => {
Some((path.take().unwrap(), service))
}
Poll::Ready(Err(e)) => return Poll::Ready(Err(e)),
Poll::Pending => {
2019-04-10 22:06:27 +00:00
done = false;
None
}
}
}
CreateServiceItem::Service(_, _) => continue,
};
if let Some((path, service)) = res {
*item = CreateServiceItem::Service(path, service);
}
}
if done {
let router = self
.fut
.drain(..)
.fold(Router::build(), |mut router, item| {
match item {
CreateServiceItem::Service(path, service) => {
router.path(&path, service);
}
CreateServiceItem::Future(_, _) => unreachable!(),
}
router
});
2019-11-21 06:17:01 +00:00
Poll::Ready(Ok(FramedAppService {
2019-04-10 22:06:27 +00:00
router: router.finish(),
state: self.state.clone(),
2019-07-20 04:50:36 +00:00
}))
2019-04-10 22:06:27 +00:00
} else {
2019-11-21 06:17:01 +00:00
Poll::Pending
2019-04-10 22:06:27 +00:00
}
}
}
2019-04-11 01:08:28 +00:00
pub struct FramedAppService<T, S> {
2019-04-10 22:06:27 +00:00
state: State<S>,
router: Router<BoxedHttpService<FramedRequest<T, S>>>,
}
2019-04-11 01:08:28 +00:00
impl<S: 'static, T: 'static> Service for FramedAppService<T, S>
2019-04-10 22:06:27 +00:00
where
2019-11-21 06:17:01 +00:00
T: AsyncRead + AsyncWrite + Unpin,
2019-04-10 22:06:27 +00:00
{
type Request = (Request, Framed<T, Codec>);
type Response = ();
type Error = Error;
type Future = BoxedResponse;
2019-11-21 06:17:01 +00:00
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
2019-04-10 22:06:27 +00:00
}
fn call(&mut self, (req, framed): (Request, Framed<T, Codec>)) -> Self::Future {
let mut path = Path::new(Url::new(req.uri().clone()));
if let Some((srv, _info)) = self.router.recognize_mut(&mut path) {
2019-04-11 02:57:34 +00:00
return srv.call(FramedRequest::new(req, framed, path, self.state.clone()));
2019-04-10 22:06:27 +00:00
}
2019-11-21 06:17:01 +00:00
SendResponse::new(framed, Response::NotFound().finish())
.then(|_| ok(()))
.boxed_local()
2019-04-10 22:06:27 +00:00
}
}