use std::rc::Rc; use std::net::SocketAddr; use actix::dev::*; use bytes::Bytes; use futures::{Future, Poll, Async}; use tokio_io::{AsyncRead, AsyncWrite}; use h1; use h2; use pipeline::Pipeline; use httprequest::HttpRequest; /// Low level http request handler pub trait HttpHandler: 'static { /// Http handler prefix fn prefix(&self) -> &str; /// Handle request fn handle(&self, req: HttpRequest) -> Pipeline; } enum HttpProtocol where T: AsyncRead + AsyncWrite + 'static, H: 'static { H1(h1::Http1), H2(h2::Http2), } pub struct HttpChannel where T: AsyncRead + AsyncWrite + 'static, H: 'static { proto: Option>, } impl HttpChannel where T: AsyncRead + AsyncWrite + 'static, H: HttpHandler + 'static { pub fn new(stream: T, addr: Option, router: Rc>, http2: bool) -> HttpChannel { if http2 { HttpChannel { proto: Some(HttpProtocol::H2( h2::Http2::new(stream, addr, router, Bytes::new()))) } } else { HttpChannel { proto: Some(HttpProtocol::H1( h1::Http1::new(stream, addr, router))) } } } } /*impl Drop for HttpChannel { fn drop(&mut self) { println!("Drop http channel"); } }*/ impl Actor for HttpChannel where T: AsyncRead + AsyncWrite + 'static, H: HttpHandler + 'static { type Context = Context; } impl Future for HttpChannel where T: AsyncRead + AsyncWrite + 'static, H: HttpHandler + 'static { type Item = (); type Error = (); fn poll(&mut self) -> Poll { match self.proto { Some(HttpProtocol::H1(ref mut h1)) => { match h1.poll() { Ok(Async::Ready(h1::Http1Result::Done)) => return Ok(Async::Ready(())), Ok(Async::Ready(h1::Http1Result::Switch)) => (), Ok(Async::NotReady) => return Ok(Async::NotReady), Err(_) => return Err(()), } } Some(HttpProtocol::H2(ref mut h2)) => return h2.poll(), None => unreachable!(), } // upgrade to h2 let proto = self.proto.take().unwrap(); match proto { HttpProtocol::H1(h1) => { let (stream, addr, router, buf) = h1.into_inner(); self.proto = Some(HttpProtocol::H2(h2::Http2::new(stream, addr, router, buf))); self.poll() } _ => unreachable!() } } }