use config::ConfigBuilder;
use error::{IntoCatch, DefaultCatch};
use futures::Future;
use middleware::Identity;
use net::ConnectionStream;
use response::{DefaultSerializer, Serializer};
use routing::{Resource, IntoResource, RoutedService};
use service::NewWebService;
use util::{BufStream, Chain};
use util::http::{HttpService, HttpMiddleware};
use std::io;
use std::net::SocketAddr;
#[derive(Debug)]
pub struct ServiceBuilder<T, Serializer, Catch, Middleware> {
resource: T,
serializer: Serializer,
catch: Catch,
middleware: Middleware,
config: ConfigBuilder,
}
impl ServiceBuilder<(), DefaultSerializer, DefaultCatch, Identity> {
pub fn new() -> Self {
ServiceBuilder {
resource: (),
serializer: DefaultSerializer::new(),
catch: DefaultCatch::new(),
middleware: Identity::new(),
config: ConfigBuilder::new(),
}
}
}
impl<T, S, C, M> ServiceBuilder<T, S, C, M> {
pub fn resource<U>(self, resource: U)
-> ServiceBuilder<<T as Chain<U>>::Output, S, C, M>
where
T: Chain<U>,
{
ServiceBuilder {
resource: self.resource.chain(resource),
serializer: self.serializer,
catch: self.catch,
middleware: self.middleware,
config: self.config,
}
}
pub fn serializer<U>(self, serializer: U)
-> ServiceBuilder<T, <S as Chain<U>>::Output, C, M>
where
S: Chain<U>,
{
ServiceBuilder {
resource: self.resource,
serializer: self.serializer.chain(serializer),
catch: self.catch,
middleware: self.middleware,
config: self.config,
}
}
pub fn config<U>(self, config: U)
-> ServiceBuilder<T, S, C, M>
where
U: Send + Sync + 'static,
{
ServiceBuilder {
resource: self.resource,
serializer: self.serializer,
catch: self.catch,
middleware: self.middleware,
config: self.config.insert(config),
}
}
pub fn middleware<U>(self, middleware: U)
-> ServiceBuilder<T, S, C, <M as Chain<U>>::Output>
where
M: Chain<U>,
{
ServiceBuilder {
resource: self.resource,
serializer: self.serializer,
catch: self.catch,
middleware: self.middleware.chain(middleware),
config: self.config,
}
}
pub fn catch<U>(self, catch: U) -> ServiceBuilder<T, S, U, M> {
ServiceBuilder {
resource: self.resource,
serializer: self.serializer,
catch,
middleware: self.middleware,
config: self.config,
}
}
pub fn build_new_service<RequestBody>(self) -> NewWebService<T::Resource, C::Catch, M>
where T: IntoResource<S, RequestBody>,
S: Serializer,
C: IntoCatch<S>,
M: HttpMiddleware<RoutedService<T::Resource, C::Catch>>,
RequestBody: BufStream,
{
let routes = self.resource.routes();
let serializer = self.serializer;
let routed = RoutedService::new(
self.resource.into_resource(serializer),
self.catch.into_catch(),
self.config.into_config(),
routes);
NewWebService::new(
routed,
self.middleware)
}
pub fn run(self, addr: &SocketAddr) -> io::Result<()>
where T: IntoResource<S, ::run::LiftReqBody>,
S: Serializer,
C: IntoCatch<S> + Send + 'static,
C::Catch: Send,
M: HttpMiddleware<RoutedService<T::Resource, C::Catch>, RequestBody = ::run::LiftReqBody> + Send + 'static,
M::Service: Send,
<M::Service as HttpService>::Future: Send,
M::ResponseBody: Send,
<M::ResponseBody as BufStream>::Item: Send,
T::Resource: Send + 'static,
<T::Resource as Resource>::Buf: Send,
<T::Resource as Resource>::Body: Send,
<T::Resource as Resource>::Future: Send,
{
::run::run(addr, self.build_new_service())
}
pub fn serve<I>(self, incoming: I) -> impl Future<Item = (), Error = ()>
where I: ConnectionStream,
I::Item: Send + 'static,
T: IntoResource<S, ::run::LiftReqBody>,
S: Serializer,
C: IntoCatch<S> + Send + 'static,
C::Catch: Send,
M: HttpMiddleware<RoutedService<T::Resource, C::Catch>, RequestBody = ::run::LiftReqBody> + Send + 'static,
M::Service: Send,
<M::Service as HttpService>::Future: Send,
M::ResponseBody: Send,
<M::ResponseBody as BufStream>::Item: Send,
T::Resource: Send + 'static,
<T::Resource as Resource>::Buf: Send,
<T::Resource as Resource>::Body: Send,
<T::Resource as Resource>::Future: Send,
{
::run::serve(incoming, self.build_new_service())
}
}