feat(server): change default dispatcher
- Deprecates the `no_proto` configuration on `Server`. It is always enabled. - Deprecates all pieces related to tokio-proto. - Makes the tokio-proto crate optional, and the `server-proto` feature can be used to completely remove the dependency. It is enabled by default.
This commit is contained in:
@@ -8,8 +8,9 @@ matrix:
|
|||||||
env: FEATURES="--features nightly"
|
env: FEATURES="--features nightly"
|
||||||
- rust: beta
|
- rust: beta
|
||||||
- rust: stable
|
- rust: stable
|
||||||
|
env: HYPER_DOCS=1
|
||||||
- rust: stable
|
- rust: stable
|
||||||
env: HYPER_NO_PROTO=1
|
env: FEATURES="--no-default-features"
|
||||||
- rust: stable
|
- rust: stable
|
||||||
env: FEATURES="--features compat"
|
env: FEATURES="--features compat"
|
||||||
- rust: 1.17.0
|
- rust: 1.17.0
|
||||||
@@ -37,7 +38,7 @@ addons:
|
|||||||
|
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
- '[ $TRAVIS_RUST_VERSION = stable ] &&
|
- '[ "$HYPER_DOCS" = "1" ] &&
|
||||||
LOCAL="~/.local" && export PATH=$LOCAL/bin:$PATH &&
|
LOCAL="~/.local" && export PATH=$LOCAL/bin:$PATH &&
|
||||||
wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz &&
|
wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz &&
|
||||||
tar xzf master.tar.gz && mkdir kcov-master/build && cd kcov-master/build &&
|
tar xzf master.tar.gz && mkdir kcov-master/build && cd kcov-master/build &&
|
||||||
@@ -51,7 +52,7 @@ after_success:
|
|||||||
fi;
|
fi;
|
||||||
done &&
|
done &&
|
||||||
kcov --coveralls-id=$TRAVIS_JOB_ID --merge target/cov target/cov/*'
|
kcov --coveralls-id=$TRAVIS_JOB_ID --merge target/cov target/cov/*'
|
||||||
- '[ $TRAVIS_PULL_REQUEST = false ] && [ $TRAVIS_RUST_VERSION = stable ] &&
|
- '[ $TRAVIS_PULL_REQUEST = false ] && [ "$HYPER_DOCS" = "1" ] &&
|
||||||
{ [ "$TRAVIS_TAG" != "" ] || [ "$TRAVIS_BRANCH" == "master" ]; } &&
|
{ [ "$TRAVIS_TAG" != "" ] || [ "$TRAVIS_BRANCH" == "master" ]; } &&
|
||||||
./.travis/docs.sh'
|
./.travis/docs.sh'
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ percent-encoding = "1.0"
|
|||||||
relay = "0.1"
|
relay = "0.1"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
tokio-core = "0.1.6"
|
tokio-core = "0.1.6"
|
||||||
tokio-proto = "0.1"
|
tokio-proto = { version = "0.1", optional = true }
|
||||||
tokio-service = "0.1"
|
tokio-service = "0.1"
|
||||||
tokio-io = "0.1"
|
tokio-io = "0.1"
|
||||||
unicase = "2.0"
|
unicase = "2.0"
|
||||||
@@ -48,4 +48,4 @@ default = ["server-proto"]
|
|||||||
nightly = []
|
nightly = []
|
||||||
raw_status = []
|
raw_status = []
|
||||||
compat = [ "http" ]
|
compat = [ "http" ]
|
||||||
server-proto = []
|
server-proto = ["tokio-proto"]
|
||||||
|
|||||||
@@ -19,8 +19,7 @@ fn main() {
|
|||||||
.with_body(PHRASE))
|
.with_body(PHRASE))
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let mut server = Http::new().bind(&addr, new_service).unwrap();
|
let server = Http::new().bind(&addr, new_service).unwrap();
|
||||||
server.no_proto();
|
|
||||||
println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap());
|
println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap());
|
||||||
server.run().unwrap();
|
server.run().unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,8 +99,7 @@ fn main() {
|
|||||||
pretty_env_logger::init().unwrap();
|
pretty_env_logger::init().unwrap();
|
||||||
let addr = "127.0.0.1:1337".parse().unwrap();
|
let addr = "127.0.0.1:1337".parse().unwrap();
|
||||||
|
|
||||||
let mut server = Http::new().bind(&addr, || Ok(ParamExample)).unwrap();
|
let server = Http::new().bind(&addr, || Ok(ParamExample)).unwrap();
|
||||||
server.no_proto();
|
|
||||||
println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap());
|
println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap());
|
||||||
server.run().unwrap();
|
server.run().unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,8 +135,7 @@ fn main() {
|
|||||||
pretty_env_logger::init().unwrap();
|
pretty_env_logger::init().unwrap();
|
||||||
let addr = "127.0.0.1:1337".parse().unwrap();
|
let addr = "127.0.0.1:1337".parse().unwrap();
|
||||||
|
|
||||||
let mut server = Http::new().bind(&addr, || Ok(ResponseExamples)).unwrap();
|
let server = Http::new().bind(&addr, || Ok(ResponseExamples)).unwrap();
|
||||||
server.no_proto();
|
|
||||||
println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap());
|
println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap());
|
||||||
server.run().unwrap();
|
server.run().unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,7 @@ fn main() {
|
|||||||
pretty_env_logger::init().unwrap();
|
pretty_env_logger::init().unwrap();
|
||||||
let addr = "127.0.0.1:1337".parse().unwrap();
|
let addr = "127.0.0.1:1337".parse().unwrap();
|
||||||
|
|
||||||
let mut server = Http::new().bind(&addr, || Ok(Echo)).unwrap();
|
let server = Http::new().bind(&addr, || Ok(Echo)).unwrap();
|
||||||
server.no_proto();
|
|
||||||
println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap());
|
println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap());
|
||||||
server.run().unwrap();
|
server.run().unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ where C: Connect,
|
|||||||
let pooled = pool.pooled(pool_key, tx);
|
let pooled = pool.pooled(pool_key, tx);
|
||||||
let conn = proto::Conn::<_, _, proto::ClientTransaction, _>::new(io, pooled.clone());
|
let conn = proto::Conn::<_, _, proto::ClientTransaction, _>::new(io, pooled.clone());
|
||||||
let dispatch = proto::dispatch::Dispatcher::new(proto::dispatch::Client::new(rx), conn);
|
let dispatch = proto::dispatch::Dispatcher::new(proto::dispatch::Client::new(rx), conn);
|
||||||
handle.spawn(dispatch.map_err(|err| error!("no_proto error: {}", err)));
|
handle.spawn(dispatch.map_err(|err| error!("client connection error: {}", err)));
|
||||||
pooled
|
pooled
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|||||||
17
src/lib.rs
17
src/lib.rs
@@ -32,6 +32,7 @@ extern crate relay;
|
|||||||
extern crate time;
|
extern crate time;
|
||||||
extern crate tokio_core as tokio;
|
extern crate tokio_core as tokio;
|
||||||
#[macro_use] extern crate tokio_io;
|
#[macro_use] extern crate tokio_io;
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
extern crate tokio_proto;
|
extern crate tokio_proto;
|
||||||
extern crate tokio_service;
|
extern crate tokio_service;
|
||||||
extern crate unicase;
|
extern crate unicase;
|
||||||
@@ -55,17 +56,13 @@ pub use proto::RawStatus;
|
|||||||
|
|
||||||
macro_rules! feat_server_proto {
|
macro_rules! feat_server_proto {
|
||||||
($($i:item)*) => ($(
|
($($i:item)*) => ($(
|
||||||
#[cfg_attr(
|
#[cfg(feature = "server-proto")]
|
||||||
not(feature = "server-proto"),
|
#[deprecated(
|
||||||
deprecated(
|
since="0.11.11",
|
||||||
since="0.11.7",
|
note="All usage of the tokio-proto crate is going away."
|
||||||
note="server-proto was recently added to default features, but you have disabled default features. A future version will remove these types if the server-proto feature is not enabled."
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
#[cfg_attr(
|
|
||||||
not(feature = "server-proto"),
|
|
||||||
allow(deprecated)
|
|
||||||
)]
|
)]
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[allow(deprecated)]
|
||||||
$i
|
$i
|
||||||
)*)
|
)*)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,14 +87,23 @@ impl<T> AsyncIo<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AsyncIo<Buf> {
|
impl AsyncIo<Buf> {
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
|
//TODO: fix proto::conn::tests to not use tokio-proto API,
|
||||||
|
//and then this cfg flag go away
|
||||||
pub fn new_buf<T: Into<Vec<u8>>>(buf: T, bytes: usize) -> AsyncIo<Buf> {
|
pub fn new_buf<T: Into<Vec<u8>>>(buf: T, bytes: usize) -> AsyncIo<Buf> {
|
||||||
AsyncIo::new(Buf::wrap(buf.into()), bytes)
|
AsyncIo::new(Buf::wrap(buf.into()), bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
|
//TODO: fix proto::conn::tests to not use tokio-proto API,
|
||||||
|
//and then this cfg flag go away
|
||||||
pub fn new_eof() -> AsyncIo<Buf> {
|
pub fn new_eof() -> AsyncIo<Buf> {
|
||||||
AsyncIo::new(Buf::wrap(Vec::new().into()), 1)
|
AsyncIo::new(Buf::wrap(Vec::new().into()), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
|
//TODO: fix proto::conn::tests to not use tokio-proto API,
|
||||||
|
//and then this cfg flag go away
|
||||||
pub fn flushed(&self) -> bool {
|
pub fn flushed(&self) -> bool {
|
||||||
self.flushed
|
self.flushed
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::{Async, AsyncSink, Future, Poll, Sink, StartSend, Stream};
|
use futures::{Async, AsyncSink, Future, Poll, Sink, StartSend, Stream};
|
||||||
use futures::sync::{mpsc, oneshot};
|
use futures::sync::{mpsc, oneshot};
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
use tokio_proto;
|
use tokio_proto;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use super::Chunk;
|
use super::Chunk;
|
||||||
|
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
pub type TokioBody = tokio_proto::streaming::Body<Chunk, ::Error>;
|
pub type TokioBody = tokio_proto::streaming::Body<Chunk, ::Error>;
|
||||||
pub type BodySender = mpsc::Sender<Result<Chunk, ::Error>>;
|
pub type BodySender = mpsc::Sender<Result<Chunk, ::Error>>;
|
||||||
|
|
||||||
@@ -16,17 +18,21 @@ pub struct Body(Inner);
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Inner {
|
enum Inner {
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
Tokio(TokioBody),
|
Tokio(TokioBody),
|
||||||
Hyper {
|
Chan {
|
||||||
close_tx: oneshot::Sender<()>,
|
close_tx: oneshot::Sender<bool>,
|
||||||
rx: mpsc::Receiver<Result<Chunk, ::Error>>,
|
rx: mpsc::Receiver<Result<Chunk, ::Error>>,
|
||||||
}
|
},
|
||||||
|
Once(Option<Chunk>),
|
||||||
|
Empty,
|
||||||
}
|
}
|
||||||
|
|
||||||
//pub(crate)
|
//pub(crate)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ChunkSender {
|
pub struct ChunkSender {
|
||||||
close_rx: oneshot::Receiver<()>,
|
close_rx: oneshot::Receiver<bool>,
|
||||||
|
close_rx_check: bool,
|
||||||
tx: BodySender,
|
tx: BodySender,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,15 +40,14 @@ impl Body {
|
|||||||
/// Return an empty body stream
|
/// Return an empty body stream
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn empty() -> Body {
|
pub fn empty() -> Body {
|
||||||
Body(Inner::Tokio(TokioBody::empty()))
|
Body(Inner::Empty)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a body stream with an associated sender half
|
/// Return a body stream with an associated sender half
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pair() -> (mpsc::Sender<Result<Chunk, ::Error>>, Body) {
|
pub fn pair() -> (mpsc::Sender<Result<Chunk, ::Error>>, Body) {
|
||||||
let (tx, rx) = TokioBody::pair();
|
let (tx, rx) = channel();
|
||||||
let rx = Body(Inner::Tokio(rx));
|
(tx.tx, rx)
|
||||||
(tx, rx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,13 +65,16 @@ impl Stream for Body {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn poll(&mut self) -> Poll<Option<Chunk>, ::Error> {
|
fn poll(&mut self) -> Poll<Option<Chunk>, ::Error> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
Inner::Tokio(ref mut rx) => rx.poll(),
|
Inner::Tokio(ref mut rx) => rx.poll(),
|
||||||
Inner::Hyper { ref mut rx, .. } => match rx.poll().expect("mpsc cannot error") {
|
Inner::Chan { ref mut rx, .. } => match rx.poll().expect("mpsc cannot error") {
|
||||||
Async::Ready(Some(Ok(chunk))) => Ok(Async::Ready(Some(chunk))),
|
Async::Ready(Some(Ok(chunk))) => Ok(Async::Ready(Some(chunk))),
|
||||||
Async::Ready(Some(Err(err))) => Err(err),
|
Async::Ready(Some(Err(err))) => Err(err),
|
||||||
Async::Ready(None) => Ok(Async::Ready(None)),
|
Async::Ready(None) => Ok(Async::Ready(None)),
|
||||||
Async::NotReady => Ok(Async::NotReady),
|
Async::NotReady => Ok(Async::NotReady),
|
||||||
},
|
},
|
||||||
|
Inner::Once(ref mut val) => Ok(Async::Ready(val.take())),
|
||||||
|
Inner::Empty => Ok(Async::Ready(None)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,9 +86,10 @@ pub fn channel() -> (ChunkSender, Body) {
|
|||||||
|
|
||||||
let tx = ChunkSender {
|
let tx = ChunkSender {
|
||||||
close_rx: close_rx,
|
close_rx: close_rx,
|
||||||
|
close_rx_check: true,
|
||||||
tx: tx,
|
tx: tx,
|
||||||
};
|
};
|
||||||
let rx = Body(Inner::Hyper {
|
let rx = Body(Inner::Chan {
|
||||||
close_tx: close_tx,
|
close_tx: close_tx,
|
||||||
rx: rx,
|
rx: rx,
|
||||||
});
|
});
|
||||||
@@ -90,10 +99,17 @@ pub fn channel() -> (ChunkSender, Body) {
|
|||||||
|
|
||||||
impl ChunkSender {
|
impl ChunkSender {
|
||||||
pub fn poll_ready(&mut self) -> Poll<(), ()> {
|
pub fn poll_ready(&mut self) -> Poll<(), ()> {
|
||||||
|
if self.close_rx_check {
|
||||||
match self.close_rx.poll() {
|
match self.close_rx.poll() {
|
||||||
Ok(Async::Ready(())) | Err(_) => return Err(()),
|
Ok(Async::Ready(true)) | Err(_) => return Err(()),
|
||||||
|
Ok(Async::Ready(false)) => {
|
||||||
|
// needed to allow converting into a plain mpsc::Receiver
|
||||||
|
// if it has been, the tx will send false to disable this check
|
||||||
|
self.close_rx_check = false;
|
||||||
|
}
|
||||||
Ok(Async::NotReady) => (),
|
Ok(Async::NotReady) => (),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.tx.poll_ready().map_err(|_| ())
|
self.tx.poll_ready().map_err(|_| ())
|
||||||
}
|
}
|
||||||
@@ -107,63 +123,67 @@ impl ChunkSender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecate soon, but can't really deprecate trait impls
|
feat_server_proto! {
|
||||||
#[doc(hidden)]
|
|
||||||
impl From<Body> for tokio_proto::streaming::Body<Chunk, ::Error> {
|
impl From<Body> for tokio_proto::streaming::Body<Chunk, ::Error> {
|
||||||
#[inline]
|
|
||||||
fn from(b: Body) -> tokio_proto::streaming::Body<Chunk, ::Error> {
|
fn from(b: Body) -> tokio_proto::streaming::Body<Chunk, ::Error> {
|
||||||
match b.0 {
|
match b.0 {
|
||||||
Inner::Tokio(b) => b,
|
Inner::Tokio(b) => b,
|
||||||
Inner::Hyper { close_tx, rx } => {
|
Inner::Chan { close_tx, rx } => {
|
||||||
warn!("converting hyper::Body into a tokio_proto Body is deprecated");
|
// disable knowing if the Rx gets dropped, since we cannot
|
||||||
::std::mem::forget(close_tx);
|
// pass this tx along.
|
||||||
|
let _ = close_tx.send(false);
|
||||||
rx.into()
|
rx.into()
|
||||||
}
|
},
|
||||||
|
Inner::Once(Some(chunk)) => TokioBody::from(chunk),
|
||||||
|
Inner::Once(None) |
|
||||||
|
Inner::Empty => TokioBody::empty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecate soon, but can't really deprecate trait impls
|
|
||||||
#[doc(hidden)]
|
|
||||||
impl From<tokio_proto::streaming::Body<Chunk, ::Error>> for Body {
|
impl From<tokio_proto::streaming::Body<Chunk, ::Error>> for Body {
|
||||||
#[inline]
|
|
||||||
fn from(tokio_body: tokio_proto::streaming::Body<Chunk, ::Error>) -> Body {
|
fn from(tokio_body: tokio_proto::streaming::Body<Chunk, ::Error>) -> Body {
|
||||||
Body(Inner::Tokio(tokio_body))
|
Body(Inner::Tokio(tokio_body))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<mpsc::Receiver<Result<Chunk, ::Error>>> for Body {
|
impl From<mpsc::Receiver<Result<Chunk, ::Error>>> for Body {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(src: mpsc::Receiver<Result<Chunk, ::Error>>) -> Body {
|
fn from(src: mpsc::Receiver<Result<Chunk, ::Error>>) -> Body {
|
||||||
TokioBody::from(src).into()
|
let (tx, _) = oneshot::channel();
|
||||||
|
Body(Inner::Chan {
|
||||||
|
close_tx: tx,
|
||||||
|
rx: src,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Chunk> for Body {
|
impl From<Chunk> for Body {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from (chunk: Chunk) -> Body {
|
fn from (chunk: Chunk) -> Body {
|
||||||
TokioBody::from(chunk).into()
|
Body(Inner::Once(Some(chunk)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Bytes> for Body {
|
impl From<Bytes> for Body {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from (bytes: Bytes) -> Body {
|
fn from (bytes: Bytes) -> Body {
|
||||||
Body::from(TokioBody::from(Chunk::from(bytes)))
|
Body::from(Chunk::from(bytes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<u8>> for Body {
|
impl From<Vec<u8>> for Body {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from (vec: Vec<u8>) -> Body {
|
fn from (vec: Vec<u8>) -> Body {
|
||||||
Body::from(TokioBody::from(Chunk::from(vec)))
|
Body::from(Chunk::from(vec))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&'static [u8]> for Body {
|
impl From<&'static [u8]> for Body {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from (slice: &'static [u8]) -> Body {
|
fn from (slice: &'static [u8]) -> Body {
|
||||||
Body::from(TokioBody::from(Chunk::from(slice)))
|
Body::from(Chunk::from(slice))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,14 +200,14 @@ impl From<Cow<'static, [u8]>> for Body {
|
|||||||
impl From<String> for Body {
|
impl From<String> for Body {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from (s: String) -> Body {
|
fn from (s: String) -> Body {
|
||||||
Body::from(TokioBody::from(Chunk::from(s.into_bytes())))
|
Body::from(Chunk::from(s.into_bytes()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&'static str> for Body {
|
impl From<&'static str> for Body {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(slice: &'static str) -> Body {
|
fn from(slice: &'static str) -> Body {
|
||||||
Body::from(TokioBody::from(Chunk::from(slice.as_bytes())))
|
Body::from(Chunk::from(slice.as_bytes()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ use std::fmt;
|
|||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use futures::{Poll, Async, AsyncSink, Stream, Sink, StartSend};
|
use futures::{Async, AsyncSink, Poll, StartSend};
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
|
use futures::{Sink, Stream};
|
||||||
use futures::task::Task;
|
use futures::task::Task;
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
use tokio_proto::streaming::pipeline::{Frame, Transport};
|
use tokio_proto::streaming::pipeline::{Frame, Transport};
|
||||||
|
|
||||||
use proto::Http1Transaction;
|
use proto::Http1Transaction;
|
||||||
@@ -51,6 +54,7 @@ where I: AsyncRead + AsyncWrite,
|
|||||||
self.io.set_flush_pipeline(enabled);
|
self.io.set_flush_pipeline(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
fn poll_incoming(&mut self) -> Poll<Option<Frame<super::MessageHead<T::Incoming>, super::Chunk, ::Error>>, io::Error> {
|
fn poll_incoming(&mut self) -> Poll<Option<Frame<super::MessageHead<T::Incoming>, super::Chunk, ::Error>>, io::Error> {
|
||||||
trace!("Conn::poll_incoming()");
|
trace!("Conn::poll_incoming()");
|
||||||
|
|
||||||
@@ -123,7 +127,7 @@ where I: AsyncRead + AsyncWrite,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_write_continue(&self) -> bool {
|
pub fn can_write_continue(&self) -> bool {
|
||||||
match self.state.writing {
|
match self.state.writing {
|
||||||
Writing::Continue(..) => true,
|
Writing::Continue(..) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
@@ -511,11 +515,6 @@ where I: AsyncRead + AsyncWrite,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close_and_shutdown(&mut self) -> Poll<(), io::Error> {
|
|
||||||
try_ready!(self.flush());
|
|
||||||
self.shutdown()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn shutdown(&mut self) -> Poll<(), io::Error> {
|
pub fn shutdown(&mut self) -> Poll<(), io::Error> {
|
||||||
match self.io.io_mut().shutdown() {
|
match self.io.io_mut().shutdown() {
|
||||||
Ok(Async::NotReady) => Ok(Async::NotReady),
|
Ok(Async::NotReady) => Ok(Async::NotReady),
|
||||||
@@ -549,6 +548,7 @@ where I: AsyncRead + AsyncWrite,
|
|||||||
|
|
||||||
// ==== tokio_proto impl ====
|
// ==== tokio_proto impl ====
|
||||||
|
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
impl<I, B, T, K> Stream for Conn<I, B, T, K>
|
impl<I, B, T, K> Stream for Conn<I, B, T, K>
|
||||||
where I: AsyncRead + AsyncWrite,
|
where I: AsyncRead + AsyncWrite,
|
||||||
B: AsRef<[u8]>,
|
B: AsRef<[u8]>,
|
||||||
@@ -567,6 +567,7 @@ where I: AsyncRead + AsyncWrite,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
impl<I, B, T, K> Sink for Conn<I, B, T, K>
|
impl<I, B, T, K> Sink for Conn<I, B, T, K>
|
||||||
where I: AsyncRead + AsyncWrite,
|
where I: AsyncRead + AsyncWrite,
|
||||||
B: AsRef<[u8]>,
|
B: AsRef<[u8]>,
|
||||||
@@ -630,10 +631,12 @@ where I: AsyncRead + AsyncWrite,
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn close(&mut self) -> Poll<(), Self::SinkError> {
|
fn close(&mut self) -> Poll<(), Self::SinkError> {
|
||||||
self.close_and_shutdown()
|
try_ready!(self.flush());
|
||||||
|
self.shutdown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
impl<I, B, T, K> Transport for Conn<I, B, T, K>
|
impl<I, B, T, K> Transport for Conn<I, B, T, K>
|
||||||
where I: AsyncRead + AsyncWrite + 'static,
|
where I: AsyncRead + AsyncWrite + 'static,
|
||||||
B: AsRef<[u8]> + 'static,
|
B: AsRef<[u8]> + 'static,
|
||||||
@@ -838,8 +841,10 @@ impl<B, K: KeepAlive> State<B, K> {
|
|||||||
|
|
||||||
// The DebugFrame and DebugChunk are simple Debug implementations that allow
|
// The DebugFrame and DebugChunk are simple Debug implementations that allow
|
||||||
// us to dump the frame into logs, without logging the entirety of the bytes.
|
// us to dump the frame into logs, without logging the entirety of the bytes.
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
struct DebugFrame<'a, T: fmt::Debug + 'a, B: AsRef<[u8]> + 'a>(&'a Frame<super::MessageHead<T>, B, ::Error>);
|
struct DebugFrame<'a, T: fmt::Debug + 'a, B: AsRef<[u8]> + 'a>(&'a Frame<super::MessageHead<T>, B, ::Error>);
|
||||||
|
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
impl<'a, T: fmt::Debug + 'a, B: AsRef<[u8]> + 'a> fmt::Debug for DebugFrame<'a, T, B> {
|
impl<'a, T: fmt::Debug + 'a, B: AsRef<[u8]> + 'a> fmt::Debug for DebugFrame<'a, T, B> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self.0 {
|
match *self.0 {
|
||||||
@@ -868,6 +873,8 @@ impl<'a, T: fmt::Debug + 'a, B: AsRef<[u8]> + 'a> fmt::Debug for DebugFrame<'a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
|
//TODO: rewrite these using dispatch instead of tokio-proto API
|
||||||
mod tests {
|
mod tests {
|
||||||
use futures::{Async, Future, Stream, Sink};
|
use futures::{Async, Future, Stream, Sink};
|
||||||
use futures::future;
|
use futures::future;
|
||||||
|
|||||||
@@ -108,6 +108,8 @@ where
|
|||||||
return Ok(Async::Ready(()));
|
return Ok(Async::Ready(()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if self.conn.can_write_continue() {
|
||||||
|
try_nb!(self.conn.flush());
|
||||||
} else if let Some(mut body) = self.body_tx.take() {
|
} else if let Some(mut body) = self.body_tx.take() {
|
||||||
let can_read_body = self.conn.can_read_body();
|
let can_read_body = self.conn.can_read_body();
|
||||||
match body.poll_ready() {
|
match body.poll_ready() {
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ use version::HttpVersion;
|
|||||||
use version::HttpVersion::{Http10, Http11};
|
use version::HttpVersion::{Http10, Http11};
|
||||||
|
|
||||||
pub use self::conn::{Conn, KeepAlive, KA};
|
pub use self::conn::{Conn, KeepAlive, KA};
|
||||||
pub use self::body::{Body, TokioBody};
|
pub use self::body::Body;
|
||||||
|
#[cfg(feature = "tokio-proto")]
|
||||||
|
pub use self::body::TokioBody;
|
||||||
pub use self::chunk::Chunk;
|
pub use self::chunk::Chunk;
|
||||||
|
|
||||||
mod body;
|
mod body;
|
||||||
|
|||||||
@@ -49,8 +49,7 @@ feat_server_proto! {
|
|||||||
|
|
||||||
pub use self::service::{const_service, service_fn};
|
pub use self::service::{const_service, service_fn};
|
||||||
|
|
||||||
/// An instance of the HTTP protocol, and implementation of tokio-proto's
|
/// A configuration of the HTTP protocol.
|
||||||
/// `ServerProto` trait.
|
|
||||||
///
|
///
|
||||||
/// This structure is used to create instances of `Server` or to spawn off tasks
|
/// This structure is used to create instances of `Server` or to spawn off tasks
|
||||||
/// which handle a connection to an HTTP server. Each instance of `Http` can be
|
/// which handle a connection to an HTTP server. Each instance of `Http` can be
|
||||||
@@ -74,7 +73,6 @@ where B: Stream<Error=::Error>,
|
|||||||
reactor: Core,
|
reactor: Core,
|
||||||
listener: TcpListener,
|
listener: TcpListener,
|
||||||
shutdown_timeout: Duration,
|
shutdown_timeout: Duration,
|
||||||
no_proto: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A stream mapping incoming IOs to new services.
|
/// A stream mapping incoming IOs to new services.
|
||||||
@@ -127,10 +125,6 @@ where
|
|||||||
|
|
||||||
// ===== impl Http =====
|
// ===== impl Http =====
|
||||||
|
|
||||||
// This is wrapped in this macro because using `Http` as a `ServerProto` will
|
|
||||||
// never trigger a deprecation warning, so we have to annoy more people to
|
|
||||||
// protect some others.
|
|
||||||
feat_server_proto! {
|
|
||||||
impl<B: AsRef<[u8]> + 'static> Http<B> {
|
impl<B: AsRef<[u8]> + 'static> Http<B> {
|
||||||
/// Creates a new instance of the HTTP protocol, ready to spawn a server or
|
/// Creates a new instance of the HTTP protocol, ready to spawn a server or
|
||||||
/// start accepting connections.
|
/// start accepting connections.
|
||||||
@@ -141,10 +135,7 @@ feat_server_proto! {
|
|||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<B: AsRef<[u8]> + 'static> Http<B> {
|
|
||||||
/// Enables or disables HTTP keep-alive.
|
/// Enables or disables HTTP keep-alive.
|
||||||
///
|
///
|
||||||
/// Default is true.
|
/// Default is true.
|
||||||
@@ -187,7 +178,6 @@ impl<B: AsRef<[u8]> + 'static> Http<B> {
|
|||||||
listener: listener,
|
listener: listener,
|
||||||
protocol: self.clone(),
|
protocol: self.clone(),
|
||||||
shutdown_timeout: Duration::new(1, 0),
|
shutdown_timeout: Duration::new(1, 0),
|
||||||
no_proto: false,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,9 +310,9 @@ impl<S, B> Server<S, B>
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure this server to not use tokio-proto infrastructure internally.
|
#[doc(hidden)]
|
||||||
|
#[deprecated(since="0.11.11", note="no_proto is always enabled")]
|
||||||
pub fn no_proto(&mut self) -> &mut Self {
|
pub fn no_proto(&mut self) -> &mut Self {
|
||||||
self.no_proto = true;
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,7 +340,7 @@ impl<S, B> Server<S, B>
|
|||||||
pub fn run_until<F>(self, shutdown_signal: F) -> ::Result<()>
|
pub fn run_until<F>(self, shutdown_signal: F) -> ::Result<()>
|
||||||
where F: Future<Item = (), Error = ()>,
|
where F: Future<Item = (), Error = ()>,
|
||||||
{
|
{
|
||||||
let Server { protocol, new_service, mut reactor, listener, shutdown_timeout, no_proto } = self;
|
let Server { protocol, new_service, mut reactor, listener, shutdown_timeout } = self;
|
||||||
|
|
||||||
let handle = reactor.handle();
|
let handle = reactor.handle();
|
||||||
|
|
||||||
@@ -367,15 +357,10 @@ impl<S, B> Server<S, B>
|
|||||||
info: Rc::downgrade(&info),
|
info: Rc::downgrade(&info),
|
||||||
};
|
};
|
||||||
info.borrow_mut().active += 1;
|
info.borrow_mut().active += 1;
|
||||||
if no_proto {
|
|
||||||
let fut = protocol.serve_connection(socket, s)
|
let fut = protocol.serve_connection(socket, s)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
.map_err(|err| error!("no_proto error: {}", err));
|
.map_err(move |err| error!("server connection error: ({}) {}", addr, err));
|
||||||
handle.spawn(fut);
|
handle.spawn(fut);
|
||||||
} else {
|
|
||||||
#[allow(deprecated)]
|
|
||||||
protocol.bind_connection(&handle, socket, addr, s);
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -669,7 +669,7 @@ fn disable_keep_alive_post_request() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn no_proto_empty_parse_eof_does_not_return_error() {
|
fn empty_parse_eof_does_not_return_error() {
|
||||||
let mut core = Core::new().unwrap();
|
let mut core = Core::new().unwrap();
|
||||||
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
|
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
|
||||||
let addr = listener.local_addr().unwrap();
|
let addr = listener.local_addr().unwrap();
|
||||||
@@ -690,7 +690,7 @@ fn no_proto_empty_parse_eof_does_not_return_error() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn no_proto_nonempty_parse_eof_returns_error() {
|
fn nonempty_parse_eof_returns_error() {
|
||||||
let mut core = Core::new().unwrap();
|
let mut core = Core::new().unwrap();
|
||||||
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
|
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
|
||||||
let addr = listener.local_addr().unwrap();
|
let addr = listener.local_addr().unwrap();
|
||||||
@@ -868,7 +868,6 @@ fn serve() -> Serve {
|
|||||||
|
|
||||||
struct ServeOptions {
|
struct ServeOptions {
|
||||||
keep_alive_disabled: bool,
|
keep_alive_disabled: bool,
|
||||||
no_proto: bool,
|
|
||||||
pipeline: bool,
|
pipeline: bool,
|
||||||
timeout: Option<Duration>,
|
timeout: Option<Duration>,
|
||||||
}
|
}
|
||||||
@@ -877,20 +876,12 @@ impl Default for ServeOptions {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
ServeOptions {
|
ServeOptions {
|
||||||
keep_alive_disabled: false,
|
keep_alive_disabled: false,
|
||||||
no_proto: env("HYPER_NO_PROTO", "1"),
|
|
||||||
pipeline: false,
|
pipeline: false,
|
||||||
timeout: None,
|
timeout: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn env(name: &str, val: &str) -> bool {
|
|
||||||
match ::std::env::var(name) {
|
|
||||||
Ok(var) => var == val,
|
|
||||||
Err(_) => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serve_with_options(options: ServeOptions) -> Serve {
|
fn serve_with_options(options: ServeOptions) -> Serve {
|
||||||
let _ = pretty_env_logger::init();
|
let _ = pretty_env_logger::init();
|
||||||
|
|
||||||
@@ -902,13 +893,12 @@ fn serve_with_options(options: ServeOptions) -> Serve {
|
|||||||
let addr = "127.0.0.1:0".parse().unwrap();
|
let addr = "127.0.0.1:0".parse().unwrap();
|
||||||
|
|
||||||
let keep_alive = !options.keep_alive_disabled;
|
let keep_alive = !options.keep_alive_disabled;
|
||||||
let no_proto = !options.no_proto;
|
|
||||||
let pipeline = options.pipeline;
|
let pipeline = options.pipeline;
|
||||||
let dur = options.timeout;
|
let dur = options.timeout;
|
||||||
|
|
||||||
let thread_name = format!("test-server-{:?}", dur);
|
let thread_name = format!("test-server-{:?}", dur);
|
||||||
let thread = thread::Builder::new().name(thread_name).spawn(move || {
|
let thread = thread::Builder::new().name(thread_name).spawn(move || {
|
||||||
let mut srv = Http::new()
|
let srv = Http::new()
|
||||||
.keep_alive(keep_alive)
|
.keep_alive(keep_alive)
|
||||||
.pipeline(pipeline)
|
.pipeline(pipeline)
|
||||||
.bind(&addr, TestService {
|
.bind(&addr, TestService {
|
||||||
@@ -916,9 +906,6 @@ fn serve_with_options(options: ServeOptions) -> Serve {
|
|||||||
_timeout: dur,
|
_timeout: dur,
|
||||||
reply: reply_rx,
|
reply: reply_rx,
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
if no_proto {
|
|
||||||
srv.no_proto();
|
|
||||||
}
|
|
||||||
addr_tx.send(srv.local_addr().unwrap()).unwrap();
|
addr_tx.send(srv.local_addr().unwrap()).unwrap();
|
||||||
srv.run_until(shutdown_rx.then(|_| Ok(()))).unwrap();
|
srv.run_until(shutdown_rx.then(|_| Ok(()))).unwrap();
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user