1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-30 18:34:36 +01:00
actix-extras/src/channel.rs

101 lines
2.7 KiB
Rust
Raw Normal View History

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;
2017-11-25 07:15:52 +01:00
use pipeline::Pipeline;
use httprequest::HttpRequest;
/// Low level http request handler
pub trait HttpHandler: 'static {
/// Http handler prefix
fn prefix(&self) -> &str;
/// Handle request
2017-11-27 04:00:57 +01:00
fn handle(&self, req: HttpRequest) -> Pipeline;
}
enum HttpProtocol<T, H>
where T: AsyncRead + AsyncWrite + 'static, H: 'static
{
H1(h1::Http1<T, H>),
H2(h2::Http2<T, H>),
}
2017-11-27 07:53:28 +01:00
#[doc(hidden)]
pub struct HttpChannel<T, H>
where T: AsyncRead + AsyncWrite + 'static, H: 'static
{
proto: Option<HttpProtocol<T, H>>,
}
impl<T, H> HttpChannel<T, H>
where T: AsyncRead + AsyncWrite + 'static, H: HttpHandler + 'static
{
pub fn new(stream: T, addr: Option<SocketAddr>, router: Rc<Vec<H>>, http2: bool)
-> HttpChannel<T, H> {
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<T: 'static, A: 'static, H: 'static> Drop for HttpChannel<T, A, H> {
fn drop(&mut self) {
println!("Drop http channel");
}
}*/
impl<T, H> Actor for HttpChannel<T, H>
where T: AsyncRead + AsyncWrite + 'static, H: HttpHandler + 'static
{
type Context = Context<Self>;
}
impl<T, H> Future for HttpChannel<T, H>
where T: AsyncRead + AsyncWrite + 'static, H: HttpHandler + 'static
{
type Item = ();
type Error = ();
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
match self.proto {
Some(HttpProtocol::H1(ref mut h1)) => {
match h1.poll() {
Ok(Async::Ready(h1::Http1Result::Done)) =>
return Ok(Async::Ready(())),
2017-11-04 21:49:05 +01:00
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!()
}
}
}