mirror of
https://github.com/actix/actix-web.git
synced 2024-11-23 10:01:06 +00:00
simplify application factory
This commit is contained in:
parent
a63d3f9a7a
commit
6f3e70a92a
6 changed files with 80 additions and 110 deletions
|
@ -410,45 +410,52 @@ where
|
||||||
self.keepalive_timer.take();
|
self.keepalive_timer.take();
|
||||||
|
|
||||||
// search handler for request
|
// search handler for request
|
||||||
for h in self.settings.handlers().iter() {
|
match self.settings.handler().handle(msg) {
|
||||||
msg = match h.handle(msg) {
|
Ok(mut pipe) => {
|
||||||
Ok(mut pipe) => {
|
if self.tasks.is_empty() {
|
||||||
if self.tasks.is_empty() {
|
match pipe.poll_io(&mut self.stream) {
|
||||||
match pipe.poll_io(&mut self.stream) {
|
Ok(Async::Ready(ready)) => {
|
||||||
Ok(Async::Ready(ready)) => {
|
// override keep-alive state
|
||||||
// override keep-alive state
|
if self.stream.keepalive() {
|
||||||
if self.stream.keepalive() {
|
self.flags.insert(Flags::KEEPALIVE);
|
||||||
self.flags.insert(Flags::KEEPALIVE);
|
} else {
|
||||||
} else {
|
self.flags.remove(Flags::KEEPALIVE);
|
||||||
self.flags.remove(Flags::KEEPALIVE);
|
}
|
||||||
}
|
// prepare stream for next response
|
||||||
// prepare stream for next response
|
self.stream.reset();
|
||||||
self.stream.reset();
|
|
||||||
|
|
||||||
if !ready {
|
if !ready {
|
||||||
let item = Entry {
|
let item = Entry {
|
||||||
pipe: EntryPipe::Task(pipe),
|
pipe: EntryPipe::Task(pipe),
|
||||||
flags: EntryFlags::EOF,
|
flags: EntryFlags::EOF,
|
||||||
};
|
};
|
||||||
self.tasks.push_back(item);
|
self.tasks.push_back(item);
|
||||||
}
|
|
||||||
continue 'outer;
|
|
||||||
}
|
|
||||||
Ok(Async::NotReady) => {}
|
|
||||||
Err(err) => {
|
|
||||||
error!("Unhandled error: {}", err);
|
|
||||||
self.flags.insert(Flags::ERROR);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
Ok(Async::NotReady) => {}
|
||||||
|
Err(err) => {
|
||||||
|
error!("Unhandled error: {}", err);
|
||||||
|
self.flags.insert(Flags::ERROR);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.tasks.push_back(Entry {
|
|
||||||
pipe: EntryPipe::Task(pipe),
|
|
||||||
flags: EntryFlags::empty(),
|
|
||||||
});
|
|
||||||
continue 'outer;
|
|
||||||
}
|
}
|
||||||
Err(msg) => msg,
|
self.tasks.push_back(Entry {
|
||||||
|
pipe: EntryPipe::Task(pipe),
|
||||||
|
flags: EntryFlags::empty(),
|
||||||
|
});
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
Err(msg) => {
|
||||||
|
// handler is not found
|
||||||
|
self.tasks.push_back(Entry {
|
||||||
|
pipe: EntryPipe::Error(ServerError::err(
|
||||||
|
Version::HTTP_11,
|
||||||
|
StatusCode::NOT_FOUND,
|
||||||
|
)),
|
||||||
|
flags: EntryFlags::empty(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -368,28 +368,20 @@ impl<H: HttpHandler + 'static> Entry<H> {
|
||||||
let psender = PayloadType::new(msg.headers(), psender);
|
let psender = PayloadType::new(msg.headers(), psender);
|
||||||
|
|
||||||
// start request processing
|
// start request processing
|
||||||
let mut task = None;
|
let task = match settings.handler().handle(msg) {
|
||||||
for h in settings.handlers().iter() {
|
Ok(task) => EntryPipe::Task(task),
|
||||||
msg = match h.handle(msg) {
|
Err(msg) => EntryPipe::Error(ServerError::err(
|
||||||
Ok(t) => {
|
Version::HTTP_2,
|
||||||
task = Some(t);
|
StatusCode::NOT_FOUND,
|
||||||
break;
|
)),
|
||||||
}
|
};
|
||||||
Err(msg) => msg,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Entry {
|
Entry {
|
||||||
task: task.map(EntryPipe::Task).unwrap_or_else(|| {
|
task,
|
||||||
EntryPipe::Error(ServerError::err(
|
recv,
|
||||||
Version::HTTP_2,
|
|
||||||
StatusCode::NOT_FOUND,
|
|
||||||
))
|
|
||||||
}),
|
|
||||||
payload: psender,
|
payload: psender,
|
||||||
stream: H2Writer::new(resp, settings),
|
stream: H2Writer::new(resp, settings),
|
||||||
flags: EntryFlags::empty(),
|
flags: EntryFlags::empty(),
|
||||||
recv,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct Socket<H: IntoHttpHandler> {
|
||||||
pub struct HttpServer<H, F>
|
pub struct HttpServer<H, F>
|
||||||
where
|
where
|
||||||
H: IntoHttpHandler + 'static,
|
H: IntoHttpHandler + 'static,
|
||||||
F: Fn() -> Vec<H> + Send + Clone,
|
F: Fn() -> H + Send + Clone,
|
||||||
{
|
{
|
||||||
factory: F,
|
factory: F,
|
||||||
host: Option<String>,
|
host: Option<String>,
|
||||||
|
@ -58,33 +58,10 @@ where
|
||||||
impl<H, F> HttpServer<H, F>
|
impl<H, F> HttpServer<H, F>
|
||||||
where
|
where
|
||||||
H: IntoHttpHandler + 'static,
|
H: IntoHttpHandler + 'static,
|
||||||
F: Fn() -> Vec<H> + Send + Clone + 'static,
|
F: Fn() -> H + Send + Clone + 'static,
|
||||||
{
|
{
|
||||||
/// Create new http server with application factory
|
/// Create new http server with application factory
|
||||||
pub fn new<F1, U>(factory: F1) -> HttpServer<H, impl Fn() -> Vec<H> + Send + Clone>
|
pub fn new(factory: F) -> HttpServer<H, F> {
|
||||||
where
|
|
||||||
F1: Fn() -> U + Send + Clone,
|
|
||||||
U: IntoIterator<Item = H> + 'static,
|
|
||||||
{
|
|
||||||
let f = move || (factory.clone())().into_iter().collect();
|
|
||||||
|
|
||||||
HttpServer {
|
|
||||||
threads: num_cpus::get(),
|
|
||||||
factory: f,
|
|
||||||
host: None,
|
|
||||||
backlog: 2048,
|
|
||||||
keep_alive: KeepAlive::Os,
|
|
||||||
shutdown_timeout: 30,
|
|
||||||
exit: false,
|
|
||||||
no_http2: false,
|
|
||||||
no_signals: false,
|
|
||||||
maxconn: 25_600,
|
|
||||||
maxconnrate: 256,
|
|
||||||
sockets: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn with_factory(factory: F) -> HttpServer<H, F> {
|
|
||||||
HttpServer {
|
HttpServer {
|
||||||
factory,
|
factory,
|
||||||
threads: num_cpus::get(),
|
threads: num_cpus::get(),
|
||||||
|
@ -489,7 +466,7 @@ where
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H: IntoHttpHandler, F: Fn() -> Vec<H> + Send + Clone> HttpServer<H, F> {
|
impl<H: IntoHttpHandler, F: Fn() -> H + Send + Clone> HttpServer<H, F> {
|
||||||
/// Start listening for incoming connections.
|
/// Start listening for incoming connections.
|
||||||
///
|
///
|
||||||
/// This method starts number of http workers in separate threads.
|
/// This method starts number of http workers in separate threads.
|
||||||
|
@ -629,7 +606,7 @@ impl<H: IntoHttpHandler, F: Fn() -> Vec<H> + Send + Clone> HttpServer<H, F> {
|
||||||
|
|
||||||
struct HttpService<F, H, Io>
|
struct HttpService<F, H, Io>
|
||||||
where
|
where
|
||||||
F: Fn() -> Vec<H>,
|
F: Fn() -> H,
|
||||||
H: IntoHttpHandler,
|
H: IntoHttpHandler,
|
||||||
Io: IoStream,
|
Io: IoStream,
|
||||||
{
|
{
|
||||||
|
@ -642,7 +619,7 @@ where
|
||||||
|
|
||||||
impl<F, H, Io> NewService for HttpService<F, H, Io>
|
impl<F, H, Io> NewService for HttpService<F, H, Io>
|
||||||
where
|
where
|
||||||
F: Fn() -> Vec<H>,
|
F: Fn() -> H,
|
||||||
H: IntoHttpHandler,
|
H: IntoHttpHandler,
|
||||||
Io: IoStream,
|
Io: IoStream,
|
||||||
{
|
{
|
||||||
|
@ -655,12 +632,9 @@ where
|
||||||
|
|
||||||
fn new_service(&self) -> Self::Future {
|
fn new_service(&self) -> Self::Future {
|
||||||
let s = ServerSettings::new(Some(self.addr), &self.host, false);
|
let s = ServerSettings::new(Some(self.addr), &self.host, false);
|
||||||
let apps: Vec<_> = (self.factory)()
|
let app = (self.factory)().into_handler();
|
||||||
.into_iter()
|
|
||||||
.map(|h| h.into_handler())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
ok(HttpServiceHandler::new(apps, self.keep_alive, s))
|
ok(HttpServiceHandler::new(app, self.keep_alive, s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,14 +654,14 @@ where
|
||||||
Io: IoStream,
|
Io: IoStream,
|
||||||
{
|
{
|
||||||
fn new(
|
fn new(
|
||||||
apps: Vec<H>, keep_alive: KeepAlive, settings: ServerSettings,
|
app: H, keep_alive: KeepAlive, settings: ServerSettings,
|
||||||
) -> HttpServiceHandler<H, Io> {
|
) -> HttpServiceHandler<H, Io> {
|
||||||
let tcp_ka = if let KeepAlive::Tcp(val) = keep_alive {
|
let tcp_ka = if let KeepAlive::Tcp(val) = keep_alive {
|
||||||
Some(time::Duration::new(val as u64, 0))
|
Some(time::Duration::new(val as u64, 0))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let settings = WorkerSettings::new(apps, keep_alive, settings);
|
let settings = WorkerSettings::new(app, keep_alive, settings);
|
||||||
|
|
||||||
HttpServiceHandler {
|
HttpServiceHandler {
|
||||||
tcp_ka,
|
tcp_ka,
|
||||||
|
@ -733,7 +707,7 @@ where
|
||||||
struct SimpleFactory<H, F, P>
|
struct SimpleFactory<H, F, P>
|
||||||
where
|
where
|
||||||
H: IntoHttpHandler,
|
H: IntoHttpHandler,
|
||||||
F: Fn() -> Vec<H> + Send + Clone,
|
F: Fn() -> H + Send + Clone,
|
||||||
P: HttpPipelineFactory<Io = TcpStream>,
|
P: HttpPipelineFactory<Io = TcpStream>,
|
||||||
{
|
{
|
||||||
pub addr: net::SocketAddr,
|
pub addr: net::SocketAddr,
|
||||||
|
@ -744,7 +718,7 @@ where
|
||||||
impl<H: IntoHttpHandler, F, P> Clone for SimpleFactory<H, F, P>
|
impl<H: IntoHttpHandler, F, P> Clone for SimpleFactory<H, F, P>
|
||||||
where
|
where
|
||||||
P: HttpPipelineFactory<Io = TcpStream>,
|
P: HttpPipelineFactory<Io = TcpStream>,
|
||||||
F: Fn() -> Vec<H> + Send + Clone,
|
F: Fn() -> H + Send + Clone,
|
||||||
{
|
{
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
SimpleFactory {
|
SimpleFactory {
|
||||||
|
@ -758,7 +732,7 @@ where
|
||||||
impl<H, F, P> ServiceFactory<H> for SimpleFactory<H, F, P>
|
impl<H, F, P> ServiceFactory<H> for SimpleFactory<H, F, P>
|
||||||
where
|
where
|
||||||
H: IntoHttpHandler + 'static,
|
H: IntoHttpHandler + 'static,
|
||||||
F: Fn() -> Vec<H> + Send + Clone + 'static,
|
F: Fn() -> H + Send + Clone + 'static,
|
||||||
P: HttpPipelineFactory<Io = TcpStream>,
|
P: HttpPipelineFactory<Io = TcpStream>,
|
||||||
{
|
{
|
||||||
fn register(&self, server: Server, lst: net::TcpListener) -> Server {
|
fn register(&self, server: Server, lst: net::TcpListener) -> Server {
|
||||||
|
@ -894,7 +868,7 @@ where
|
||||||
|
|
||||||
struct DefaultPipelineFactory<F, H, Io>
|
struct DefaultPipelineFactory<F, H, Io>
|
||||||
where
|
where
|
||||||
F: Fn() -> Vec<H> + Send + Clone,
|
F: Fn() -> H + Send + Clone,
|
||||||
{
|
{
|
||||||
factory: F,
|
factory: F,
|
||||||
host: Option<String>,
|
host: Option<String>,
|
||||||
|
@ -906,7 +880,7 @@ where
|
||||||
impl<F, H, Io> DefaultPipelineFactory<F, H, Io>
|
impl<F, H, Io> DefaultPipelineFactory<F, H, Io>
|
||||||
where
|
where
|
||||||
Io: IoStream + Send,
|
Io: IoStream + Send,
|
||||||
F: Fn() -> Vec<H> + Send + Clone + 'static,
|
F: Fn() -> H + Send + Clone + 'static,
|
||||||
H: IntoHttpHandler + 'static,
|
H: IntoHttpHandler + 'static,
|
||||||
{
|
{
|
||||||
fn new(
|
fn new(
|
||||||
|
@ -925,7 +899,7 @@ where
|
||||||
impl<F, H, Io> Clone for DefaultPipelineFactory<F, H, Io>
|
impl<F, H, Io> Clone for DefaultPipelineFactory<F, H, Io>
|
||||||
where
|
where
|
||||||
Io: IoStream,
|
Io: IoStream,
|
||||||
F: Fn() -> Vec<H> + Send + Clone,
|
F: Fn() -> H + Send + Clone,
|
||||||
H: IntoHttpHandler,
|
H: IntoHttpHandler,
|
||||||
{
|
{
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
|
@ -942,7 +916,7 @@ where
|
||||||
impl<F, H, Io> HttpPipelineFactory for DefaultPipelineFactory<F, H, Io>
|
impl<F, H, Io> HttpPipelineFactory for DefaultPipelineFactory<F, H, Io>
|
||||||
where
|
where
|
||||||
Io: IoStream + Send,
|
Io: IoStream + Send,
|
||||||
F: Fn() -> Vec<H> + Send + Clone + 'static,
|
F: Fn() -> H + Send + Clone + 'static,
|
||||||
H: IntoHttpHandler + 'static,
|
H: IntoHttpHandler + 'static,
|
||||||
{
|
{
|
||||||
type Io = Io;
|
type Io = Io;
|
||||||
|
|
|
@ -174,13 +174,12 @@ const HW_BUFFER_SIZE: usize = 32_768;
|
||||||
/// sys.run();
|
/// sys.run();
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new<F, U, H>(factory: F) -> HttpServer<H, impl Fn() -> Vec<H> + Send + Clone>
|
pub fn new<F, H>(factory: F) -> HttpServer<H, F>
|
||||||
where
|
where
|
||||||
F: Fn() -> U + Send + Clone + 'static,
|
F: Fn() -> H + Send + Clone + 'static,
|
||||||
U: IntoIterator<Item = H>,
|
|
||||||
H: IntoHttpHandler + 'static,
|
H: IntoHttpHandler + 'static,
|
||||||
{
|
{
|
||||||
HttpServer::with_factory(move || (factory.clone())().into_iter().collect())
|
HttpServer::new(factory)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
|
|
@ -136,7 +136,7 @@ const DATE_VALUE_LENGTH: usize = 29;
|
||||||
pub(crate) struct WorkerSettings<H>(Rc<Inner<H>>);
|
pub(crate) struct WorkerSettings<H>(Rc<Inner<H>>);
|
||||||
|
|
||||||
struct Inner<H> {
|
struct Inner<H> {
|
||||||
h: Vec<H>,
|
handler: H,
|
||||||
keep_alive: u64,
|
keep_alive: u64,
|
||||||
ka_enabled: bool,
|
ka_enabled: bool,
|
||||||
bytes: Rc<SharedBytesPool>,
|
bytes: Rc<SharedBytesPool>,
|
||||||
|
@ -153,7 +153,7 @@ impl<H> Clone for WorkerSettings<H> {
|
||||||
|
|
||||||
impl<H> WorkerSettings<H> {
|
impl<H> WorkerSettings<H> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
h: Vec<H>, keep_alive: KeepAlive, settings: ServerSettings,
|
handler: H, keep_alive: KeepAlive, settings: ServerSettings,
|
||||||
) -> WorkerSettings<H> {
|
) -> WorkerSettings<H> {
|
||||||
let (keep_alive, ka_enabled) = match keep_alive {
|
let (keep_alive, ka_enabled) = match keep_alive {
|
||||||
KeepAlive::Timeout(val) => (val as u64, true),
|
KeepAlive::Timeout(val) => (val as u64, true),
|
||||||
|
@ -162,7 +162,7 @@ impl<H> WorkerSettings<H> {
|
||||||
};
|
};
|
||||||
|
|
||||||
WorkerSettings(Rc::new(Inner {
|
WorkerSettings(Rc::new(Inner {
|
||||||
h,
|
handler,
|
||||||
keep_alive,
|
keep_alive,
|
||||||
ka_enabled,
|
ka_enabled,
|
||||||
bytes: Rc::new(SharedBytesPool::new()),
|
bytes: Rc::new(SharedBytesPool::new()),
|
||||||
|
@ -176,8 +176,8 @@ impl<H> WorkerSettings<H> {
|
||||||
self.0.node.borrow_mut()
|
self.0.node.borrow_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handlers(&self) -> &Vec<H> {
|
pub fn handler(&self) -> &H {
|
||||||
&self.0.h
|
&self.0.handler
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn keep_alive_timer(&self) -> Option<Delay> {
|
pub fn keep_alive_timer(&self) -> Option<Delay> {
|
||||||
|
|
12
src/test.rs
12
src/test.rs
|
@ -103,14 +103,12 @@ impl TestServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start new test server with application factory
|
/// Start new test server with application factory
|
||||||
pub fn with_factory<F, U, H>(factory: F) -> Self
|
pub fn with_factory<F, H>(factory: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn() -> U + Send + Clone + 'static,
|
F: Fn() -> H + Send + Clone + 'static,
|
||||||
U: IntoIterator<Item = H>,
|
|
||||||
H: IntoHttpHandler + 'static,
|
H: IntoHttpHandler + 'static,
|
||||||
{
|
{
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
let factory = move || (factory.clone())().into_iter().collect();
|
|
||||||
|
|
||||||
// run server in separate thread
|
// run server in separate thread
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
|
@ -118,7 +116,7 @@ impl TestServer {
|
||||||
let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap();
|
let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap();
|
||||||
let local_addr = tcp.local_addr().unwrap();
|
let local_addr = tcp.local_addr().unwrap();
|
||||||
|
|
||||||
let _ = HttpServer::with_factory(factory)
|
let _ = HttpServer::new(factory)
|
||||||
.disable_signals()
|
.disable_signals()
|
||||||
.listen(tcp)
|
.listen(tcp)
|
||||||
.keep_alive(5)
|
.keep_alive(5)
|
||||||
|
@ -328,10 +326,10 @@ where
|
||||||
|
|
||||||
let sys = System::new("actix-test-server");
|
let sys = System::new("actix-test-server");
|
||||||
let state = self.state;
|
let state = self.state;
|
||||||
let mut srv = HttpServer::with_factory(move || {
|
let mut srv = HttpServer::new(move || {
|
||||||
let mut app = TestApp::new(state());
|
let mut app = TestApp::new(state());
|
||||||
config(&mut app);
|
config(&mut app);
|
||||||
vec![app]
|
app
|
||||||
}).workers(1)
|
}).workers(1)
|
||||||
.keep_alive(5)
|
.keep_alive(5)
|
||||||
.disable_signals();
|
.disable_signals();
|
||||||
|
|
Loading…
Reference in a new issue