1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-24 16:02:59 +01:00
actix-extras/src/server.rs

167 lines
5.0 KiB
Rust
Raw Normal View History

use std::{io, net, mem};
2017-10-07 06:48:14 +02:00
use std::rc::Rc;
use std::collections::VecDeque;
use actix::dev::*;
use futures::{Future, Poll, Async};
use tokio_core::net::{TcpListener, TcpStream};
use task::{Task, RequestInfo};
2017-10-07 06:48:14 +02:00
use reader::Reader;
use router::{Router, RoutingMap};
2017-10-08 23:56:51 +02:00
/// An HTTP Server
2017-10-07 06:48:14 +02:00
pub struct HttpServer {
router: Rc<Router>,
}
impl Actor for HttpServer {
type Context = Context<Self>;
}
impl HttpServer {
2017-10-07 08:14:13 +02:00
/// Create new http server with specified `RoutingMap`
2017-10-07 06:48:14 +02:00
pub fn new(routes: RoutingMap) -> Self {
HttpServer {router: Rc::new(routes.into_router())}
}
2017-10-07 08:14:13 +02:00
/// Start listening for incomming connections.
2017-10-07 06:48:14 +02:00
pub fn serve<Addr>(self, addr: &net::SocketAddr) -> io::Result<Addr>
where Self: ActorAddress<Self, Addr>
{
let tcp = TcpListener::bind(addr, Arbiter::handle())?;
Ok(HttpServer::create(move |ctx| {
ctx.add_stream(tcp.incoming());
self
}))
}
}
impl ResponseType<(TcpStream, net::SocketAddr)> for HttpServer {
type Item = ();
type Error = ();
}
impl StreamHandler<(TcpStream, net::SocketAddr), io::Error> for HttpServer {}
impl Handler<(TcpStream, net::SocketAddr), io::Error> for HttpServer {
fn handle(&mut self, msg: (TcpStream, net::SocketAddr), _: &mut Context<Self>)
-> Response<Self, (TcpStream, net::SocketAddr)>
{
Arbiter::handle().spawn(
HttpChannel{router: Rc::clone(&self.router),
addr: msg.1,
stream: msg.0,
reader: Reader::new(),
error: false,
2017-10-07 06:48:14 +02:00
items: VecDeque::new(),
inactive: Vec::new(),
});
2017-10-07 09:22:09 +02:00
Self::empty()
2017-10-07 06:48:14 +02:00
}
}
struct Entry {
task: Task,
req: RequestInfo,
2017-10-07 06:48:14 +02:00
eof: bool,
error: bool,
finished: bool,
}
pub struct HttpChannel {
router: Rc<Router>,
#[allow(dead_code)]
addr: net::SocketAddr,
stream: TcpStream,
reader: Reader,
error: bool,
2017-10-07 06:48:14 +02:00
items: VecDeque<Entry>,
inactive: Vec<Entry>,
}
impl Actor for HttpChannel {
type Context = Context<Self>;
}
impl Future for HttpChannel {
type Item = ();
type Error = ();
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
loop {
// check in-flight messages
let mut idx = 0;
while idx < self.items.len() {
if idx == 0 {
if self.items[idx].error {
return Err(())
}
// this is anoying
let req: &RequestInfo = unsafe {
mem::transmute(&self.items[idx].req)
};
match self.items[idx].task.poll_io(&mut self.stream, req)
{
2017-10-07 06:48:14 +02:00
Ok(Async::Ready(val)) => {
let mut item = self.items.pop_front().unwrap();
if !val {
item.eof = true;
self.inactive.push(item);
}
continue
},
Ok(Async::NotReady) => (),
Err(_) => {
// it is not possible to recover from error
// during task handling, so just drop connection
return Err(())
}
2017-10-07 06:48:14 +02:00
}
} else if !self.items[idx].finished {
match self.items[idx].task.poll() {
Ok(Async::Ready(_)) =>
self.items[idx].finished = true,
Ok(Async::NotReady) => (),
Err(_) =>
self.items[idx].error = true,
}
}
idx += 1;
}
// check for parse error
if self.items.is_empty() && self.error {
}
2017-10-07 06:48:14 +02:00
// read incoming data
if !self.error {
match self.reader.parse(&mut self.stream) {
Ok(Async::Ready((req, payload))) => {
let info = RequestInfo::new(&req);
self.items.push_back(
Entry {task: self.router.call(req, payload),
req: info,
eof: false,
error: false,
finished: false});
}
Ok(Async::NotReady) =>
return Ok(Async::NotReady),
Err(err) => return Err(())
//self.items.push_back(
// Entry {task: Task::reply(err),
// eof: false,
// error: false,
// finished: false})
}
2017-10-07 06:48:14 +02:00
}
}
}
}