1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
use super::{rootservice::RootService, Request, Response};
use contrib::BodyParser;
use futures::{Future, Stream};
use hyper::server::conn::Http;
use native_tls::TlsAcceptor;
use proto::{ArcHandler, ArcService, MiddleWare};
use routing::Router;
use std::{io, sync::Arc};
use tokio::{self, net::TcpListener};
use tokio_tls::TlsAcceptorExt;

/// The main server, the ArcReactor is where you mount your routes, middlewares
/// and initiate the server.
///
/// #Examples
///
/// ```rust,no_run
/// extern crate arc_reactor;
/// extern crate tokio;
/// use arc_reactor::core::ArcReactor;
///
/// fn main() {
/// 	let server = ArcReactor::default()
/// 		.port(1234)
/// 		.start()
/// 		.expect("couldn't start server");
/// 	tokio::run(server);
/// }
/// ```
pub struct ArcReactor {
	port: i16,
	arc_handler: ArcHandler,
	tls_acceptor: Option<Arc<TlsAcceptor>>,
}

impl Default for ArcReactor {
	fn default() -> Self {
		ArcReactor {
			port: 8080,
			arc_handler: ArcHandler {
				before: Some(mw![BodyParser]),
				after: None,
				handler: None,
			},
			tls_acceptor: None,
		}
	}
}

impl ArcReactor {
	/// Creates an instance of the server.
	/// with a default port of `8080`
	pub fn new() -> Self {
		ArcReactor::default()
	}

	/// Sets the port for the server to listen on and returns the instance.
	pub fn port(mut self, port: i16) -> Self {
		self.port = port;

		self
	}

	/// set the TlsAcceptor
	/// check the `examples` folder for more info.
	pub fn tls(mut self, acceptor: TlsAcceptor) -> Self {
		self.tls_acceptor = Some(Arc::new(acceptor));

		self
	}

	/// Mounts the Router on the ArcReactor.
	pub fn routes(mut self, routes: Router) -> Self {
		let routes = Box::new(routes) as Box<ArcService>;
		self.arc_handler.handler = Some(routes);

		self
	}

	pub fn service<S: ArcService + 'static>(mut self, service: S) -> Self {
		let service = Box::new(service) as Box<ArcService>;
		self.arc_handler.handler = Some(service);

		self
	}

	pub fn before<M>(mut self, before: M) -> Self
	where
		M: MiddleWare<Request> + 'static,
	{
		self.arc_handler.before = Some(Box::new(before));

		self
	}

	pub fn after<M>(mut self, after: M) -> Self
	where
		M: MiddleWare<Response> + 'static,
	{
		self.arc_handler.after = Some(Box::new(after));

		self
	}

	/// Binds the listener and returns a future representing the server
	/// this future should be spawned on the tokio runtime.
	///
	/// # Panics
	///
	/// Calling this function will panic if: no routes are supplied, or it
	/// cannot start the main event loop.

	pub fn start(self) -> Result<impl Future<Item = (), Error = ()> + Send, io::Error> {
		let ArcReactor {
			port,
			arc_handler,
			tls_acceptor: acceptor,
		} = self;

		let addr = format!("0.0.0.0:{}", port).parse().unwrap();

		info!("Binding to port {}", port);

		let listener = TcpListener::bind(&addr)?;

		let http = Http::new();

		let conn_stream_future = listener
			.incoming()
			.map_err(|err| error!("error accepting connection: {}", err))
			.for_each(move |socket| {
				let service = arc_handler.clone();
				let remote_ip = socket.peer_addr().ok();
				// user has configured a tls acceptor
				if let Some(ref acceptor) = acceptor {
					let http_clone = http.clone();
					let connection_future = acceptor
						.accept_async(socket)
						.map_err(|err| error!("TLS Handshake Error: {}", err))
						.and_then(move |socket| {
							// handshake successful
							http_clone
								.serve_connection(socket, RootService { service, remote_ip })
								.map_err(|err| error!("serve_connection Error: {}", err))
								.and_then(|_| Ok(()))
						});

					tokio::spawn(connection_future);
				} else {
					// default to http
					let connection_future = http
						.serve_connection(socket, RootService { service, remote_ip })
						.map_err(|err| error!("serve_connection Error: {}", err))
						.and_then(|_| Ok(()));

					tokio::spawn(connection_future);
				}

				Ok(())
			});

		Ok(conn_stream_future)
	}
}