feat(server): Make the server code an optional feature (#2334)
cc #2223 BREAKING CHANGE: The HTTP server code is now an optional feature. To enable the server, add `features = ["server"]` to the dependency in your `Cargo.toml`.
This commit is contained in:
@@ -75,6 +75,7 @@ default = [
|
|||||||
"runtime",
|
"runtime",
|
||||||
"stream",
|
"stream",
|
||||||
"client",
|
"client",
|
||||||
|
"server",
|
||||||
"http1",
|
"http1",
|
||||||
"http2",
|
"http2",
|
||||||
]
|
]
|
||||||
@@ -82,6 +83,7 @@ full = [
|
|||||||
"client",
|
"client",
|
||||||
"http1",
|
"http1",
|
||||||
"http2",
|
"http2",
|
||||||
|
"server",
|
||||||
"stream",
|
"stream",
|
||||||
"runtime",
|
"runtime",
|
||||||
]
|
]
|
||||||
@@ -100,7 +102,9 @@ tcp = [
|
|||||||
http1 = []
|
http1 = []
|
||||||
http2 = ["h2"]
|
http2 = ["h2"]
|
||||||
|
|
||||||
|
# Client/Server
|
||||||
client = []
|
client = []
|
||||||
|
server = []
|
||||||
|
|
||||||
# `impl Stream` for things
|
# `impl Stream` for things
|
||||||
stream = []
|
stream = []
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ use crate::common::{task, watch, Pin, Poll};
|
|||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
#[cfg(feature = "client")]
|
#[cfg(feature = "client")]
|
||||||
use crate::common::{Future, Never};
|
use crate::common::{Future, Never};
|
||||||
#[cfg(feature = "http2")]
|
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
|
||||||
use crate::proto::h2::ping;
|
use crate::proto::h2::ping;
|
||||||
use crate::upgrade::OnUpgrade;
|
use crate::upgrade::OnUpgrade;
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ enum Kind {
|
|||||||
want_tx: watch::Sender,
|
want_tx: watch::Sender,
|
||||||
rx: mpsc::Receiver<Result<Bytes, crate::Error>>,
|
rx: mpsc::Receiver<Result<Bytes, crate::Error>>,
|
||||||
},
|
},
|
||||||
#[cfg(feature = "http2")]
|
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
|
||||||
H2 {
|
H2 {
|
||||||
ping: ping::Recorder,
|
ping: ping::Recorder,
|
||||||
content_length: DecodedLength,
|
content_length: DecodedLength,
|
||||||
@@ -200,7 +200,7 @@ impl Body {
|
|||||||
Body { kind, extra: None }
|
Body { kind, extra: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "http2")]
|
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
|
||||||
pub(crate) fn h2(
|
pub(crate) fn h2(
|
||||||
recv: h2::RecvStream,
|
recv: h2::RecvStream,
|
||||||
content_length: DecodedLength,
|
content_length: DecodedLength,
|
||||||
@@ -301,7 +301,7 @@ impl Body {
|
|||||||
None => Poll::Ready(None),
|
None => Poll::Ready(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "http2")]
|
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
|
||||||
Kind::H2 {
|
Kind::H2 {
|
||||||
ref ping,
|
ref ping,
|
||||||
recv: ref mut h2,
|
recv: ref mut h2,
|
||||||
@@ -359,7 +359,7 @@ impl HttpBody for Body {
|
|||||||
#[cfg_attr(not(feature = "http2"), allow(unused))] cx: &mut task::Context<'_>,
|
#[cfg_attr(not(feature = "http2"), allow(unused))] cx: &mut task::Context<'_>,
|
||||||
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
#[cfg(feature = "http2")]
|
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
|
||||||
Kind::H2 {
|
Kind::H2 {
|
||||||
recv: ref mut h2,
|
recv: ref mut h2,
|
||||||
ref ping,
|
ref ping,
|
||||||
@@ -379,7 +379,7 @@ impl HttpBody for Body {
|
|||||||
match self.kind {
|
match self.kind {
|
||||||
Kind::Once(ref val) => val.is_none(),
|
Kind::Once(ref val) => val.is_none(),
|
||||||
Kind::Chan { content_length, .. } => content_length == DecodedLength::ZERO,
|
Kind::Chan { content_length, .. } => content_length == DecodedLength::ZERO,
|
||||||
#[cfg(feature = "http2")]
|
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
|
||||||
Kind::H2 { recv: ref h2, .. } => h2.is_end_stream(),
|
Kind::H2 { recv: ref h2, .. } => h2.is_end_stream(),
|
||||||
#[cfg(feature = "stream")]
|
#[cfg(feature = "stream")]
|
||||||
Kind::Wrapped(..) => false,
|
Kind::Wrapped(..) => false,
|
||||||
@@ -405,7 +405,7 @@ impl HttpBody for Body {
|
|||||||
#[cfg(feature = "stream")]
|
#[cfg(feature = "stream")]
|
||||||
Kind::Wrapped(..) => SizeHint::default(),
|
Kind::Wrapped(..) => SizeHint::default(),
|
||||||
Kind::Chan { content_length, .. } => opt_len!(content_length),
|
Kind::Chan { content_length, .. } => opt_len!(content_length),
|
||||||
#[cfg(feature = "http2")]
|
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
|
||||||
Kind::H2 { content_length, .. } => opt_len!(content_length),
|
Kind::H2 { content_length, .. } => opt_len!(content_length),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/cfg.rs
18
src/cfg.rs
@@ -11,16 +11,19 @@ macro_rules! cfg_feature {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! cfg_any_http {
|
macro_rules! cfg_proto {
|
||||||
($($item:item)*) => {
|
($($item:item)*) => {
|
||||||
cfg_feature! {
|
cfg_feature! {
|
||||||
#![any(feature = "http1", feature = "http2")]
|
#![all(
|
||||||
|
any(feature = "http1", feature = "http2"),
|
||||||
|
any(feature = "client", feature = "server"),
|
||||||
|
)]
|
||||||
$($item)*
|
$($item)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_any_http! {
|
cfg_proto! {
|
||||||
macro_rules! cfg_http1 {
|
macro_rules! cfg_http1 {
|
||||||
($($item:item)*) => {
|
($($item:item)*) => {
|
||||||
cfg_feature! {
|
cfg_feature! {
|
||||||
@@ -47,4 +50,13 @@ cfg_any_http! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! cfg_server {
|
||||||
|
($($item:item)*) => {
|
||||||
|
cfg_feature! {
|
||||||
|
#![feature = "server"]
|
||||||
|
$($item)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,23 @@ use std::future::Future;
|
|||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
use crate::body::{Body, HttpBody};
|
use crate::body::{Body, HttpBody};
|
||||||
#[cfg(feature = "http2")]
|
#[cfg(feature = "http2")]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
use crate::proto::h2::server::H2Stream;
|
use crate::proto::h2::server::H2Stream;
|
||||||
use crate::rt::Executor;
|
use crate::rt::Executor;
|
||||||
|
#[cfg(feature = "server")]
|
||||||
use crate::server::conn::spawn_all::{NewSvcTask, Watcher};
|
use crate::server::conn::spawn_all::{NewSvcTask, Watcher};
|
||||||
|
#[cfg(feature = "server")]
|
||||||
use crate::service::HttpService;
|
use crate::service::HttpService;
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub trait ConnStreamExec<F, B: HttpBody>: Clone {
|
pub trait ConnStreamExec<F, B: HttpBody>: Clone {
|
||||||
fn execute_h2stream(&mut self, fut: H2Stream<F, B>);
|
fn execute_h2stream(&mut self, fut: H2Stream<F, B>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub trait NewSvcExec<I, N, S: HttpService<Body>, E, W: Watcher<I, S, E>>: Clone {
|
pub trait NewSvcExec<I, N, S: HttpService<Body>, E, W: Watcher<I, S, E>>: Clone {
|
||||||
fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>);
|
fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>);
|
||||||
}
|
}
|
||||||
@@ -60,6 +66,7 @@ impl fmt::Debug for Exec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
impl<F, B> ConnStreamExec<F, B> for Exec
|
impl<F, B> ConnStreamExec<F, B> for Exec
|
||||||
where
|
where
|
||||||
H2Stream<F, B>: Future<Output = ()> + Send + 'static,
|
H2Stream<F, B>: Future<Output = ()> + Send + 'static,
|
||||||
@@ -70,6 +77,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for Exec
|
impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for Exec
|
||||||
where
|
where
|
||||||
NewSvcTask<I, N, S, E, W>: Future<Output = ()> + Send + 'static,
|
NewSvcTask<I, N, S, E, W>: Future<Output = ()> + Send + 'static,
|
||||||
@@ -83,6 +91,7 @@ where
|
|||||||
|
|
||||||
// ==== impl Executor =====
|
// ==== impl Executor =====
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
impl<E, F, B> ConnStreamExec<F, B> for E
|
impl<E, F, B> ConnStreamExec<F, B> for E
|
||||||
where
|
where
|
||||||
E: Executor<H2Stream<F, B>> + Clone,
|
E: Executor<H2Stream<F, B>> + Clone,
|
||||||
@@ -94,6 +103,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for E
|
impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for E
|
||||||
where
|
where
|
||||||
E: Executor<NewSvcTask<I, N, S, E, W>> + Clone,
|
E: Executor<NewSvcTask<I, N, S, E, W>> + Clone,
|
||||||
@@ -119,7 +129,7 @@ pub struct H2Stream<F, B>(std::marker::PhantomData<(F, B)>);
|
|||||||
impl<F, B, E> Future for H2Stream<F, B>
|
impl<F, B, E> Future for H2Stream<F, B>
|
||||||
where
|
where
|
||||||
F: Future<Output = Result<http::Response<B>, E>>,
|
F: Future<Output = Result<http::Response<B>, E>>,
|
||||||
B: HttpBody,
|
B: crate::body::HttpBody,
|
||||||
B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
|
B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
|
||||||
E: Into<Box<dyn std::error::Error + Send + Sync>>,
|
E: Into<Box<dyn std::error::Error + Send + Sync>>,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ pub(crate) struct Rewind<T> {
|
|||||||
|
|
||||||
impl<T> Rewind<T> {
|
impl<T> Rewind<T> {
|
||||||
#[cfg(any(feature = "http2", test))]
|
#[cfg(any(feature = "http2", test))]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub(crate) fn new(io: T) -> Self {
|
pub(crate) fn new(io: T) -> Self {
|
||||||
Rewind {
|
Rewind {
|
||||||
pre: None,
|
pre: None,
|
||||||
@@ -29,7 +30,7 @@ impl<T> Rewind<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(all(feature = "http1", feature = "http2"), test))]
|
#[cfg(any(all(feature = "http1", feature = "http2", feature = "server"), test))]
|
||||||
pub(crate) fn rewind(&mut self, bs: Bytes) {
|
pub(crate) fn rewind(&mut self, bs: Bytes) {
|
||||||
debug_assert!(self.pre.is_none());
|
debug_assert!(self.pre.is_none());
|
||||||
self.pre = Some(bs);
|
self.pre = Some(bs);
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ macro_rules! ready {
|
|||||||
|
|
||||||
pub(crate) mod buf;
|
pub(crate) mod buf;
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub(crate) mod date;
|
pub(crate) mod date;
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub(crate) mod drain;
|
pub(crate) mod drain;
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
pub(crate) mod exec;
|
pub(crate) mod exec;
|
||||||
@@ -24,8 +26,6 @@ pub(crate) mod sync_wrapper;
|
|||||||
pub(crate) mod task;
|
pub(crate) mod task;
|
||||||
pub(crate) mod watch;
|
pub(crate) mod watch;
|
||||||
|
|
||||||
//#[cfg(any(feature = "http1", feature = "http2"))]
|
|
||||||
//pub(crate) use self::exec::{BoxSendFuture, Exec};
|
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
#[cfg(feature = "client")]
|
#[cfg(feature = "client")]
|
||||||
pub(crate) use self::lazy::{lazy, Started as Lazy};
|
pub(crate) use self::lazy::{lazy, Started as Lazy};
|
||||||
@@ -33,6 +33,7 @@ pub use self::never::Never;
|
|||||||
pub(crate) use self::task::Poll;
|
pub(crate) use self::task::Poll;
|
||||||
|
|
||||||
// group up types normally needed for `Future`
|
// group up types normally needed for `Future`
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
cfg_proto! {
|
||||||
pub(crate) use std::marker::Unpin;
|
pub(crate) use std::marker::Unpin;
|
||||||
|
}
|
||||||
pub(crate) use std::{future::Future, pin::Pin};
|
pub(crate) use std::{future::Future, pin::Pin};
|
||||||
|
|||||||
21
src/error.rs
21
src/error.rs
@@ -36,10 +36,15 @@ pub(crate) enum Kind {
|
|||||||
/// Error occurred while connecting.
|
/// Error occurred while connecting.
|
||||||
Connect,
|
Connect,
|
||||||
/// Error creating a TcpListener.
|
/// Error creating a TcpListener.
|
||||||
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "tcp"))]
|
#[cfg(all(
|
||||||
|
any(feature = "http1", feature = "http2"),
|
||||||
|
feature = "tcp",
|
||||||
|
feature = "server"
|
||||||
|
))]
|
||||||
Listen,
|
Listen,
|
||||||
/// Error accepting on an Incoming stream.
|
/// Error accepting on an Incoming stream.
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
Accept,
|
Accept,
|
||||||
/// Error while reading a body from connection.
|
/// Error while reading a body from connection.
|
||||||
#[cfg(any(feature = "http1", feature = "http2", feature = "stream"))]
|
#[cfg(any(feature = "http1", feature = "http2", feature = "stream"))]
|
||||||
@@ -77,6 +82,7 @@ pub(crate) enum User {
|
|||||||
Body,
|
Body,
|
||||||
/// Error calling user's MakeService.
|
/// Error calling user's MakeService.
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
MakeService,
|
MakeService,
|
||||||
/// Error from future of user's Service.
|
/// Error from future of user's Service.
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
@@ -85,6 +91,7 @@ pub(crate) enum User {
|
|||||||
///
|
///
|
||||||
/// For example, sending both `content-length` and `transfer-encoding`.
|
/// For example, sending both `content-length` and `transfer-encoding`.
|
||||||
#[cfg(feature = "http1")]
|
#[cfg(feature = "http1")]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
UnexpectedHeader,
|
UnexpectedHeader,
|
||||||
/// User tried to create a Request with bad version.
|
/// User tried to create a Request with bad version.
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
@@ -96,6 +103,7 @@ pub(crate) enum User {
|
|||||||
UnsupportedRequestMethod,
|
UnsupportedRequestMethod,
|
||||||
/// User tried to respond with a 1xx (not 101) response code.
|
/// User tried to respond with a 1xx (not 101) response code.
|
||||||
#[cfg(feature = "http1")]
|
#[cfg(feature = "http1")]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
UnsupportedStatusCode,
|
UnsupportedStatusCode,
|
||||||
/// User tried to send a Request with Client with non-absolute URI.
|
/// User tried to send a Request with Client with non-absolute URI.
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
@@ -178,6 +186,7 @@ impl Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "http1")]
|
#[cfg(feature = "http1")]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub(crate) fn kind(&self) -> &Kind {
|
pub(crate) fn kind(&self) -> &Kind {
|
||||||
&self.inner.kind
|
&self.inner.kind
|
||||||
}
|
}
|
||||||
@@ -234,11 +243,13 @@ impl Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "tcp"))]
|
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "tcp"))]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub(crate) fn new_listen<E: Into<Cause>>(cause: E) -> Error {
|
pub(crate) fn new_listen<E: Into<Cause>>(cause: E) -> Error {
|
||||||
Error::new(Kind::Listen).with(cause)
|
Error::new(Kind::Listen).with(cause)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub(crate) fn new_accept<E: Into<Cause>>(cause: E) -> Error {
|
pub(crate) fn new_accept<E: Into<Cause>>(cause: E) -> Error {
|
||||||
Error::new(Kind::Accept).with(cause)
|
Error::new(Kind::Accept).with(cause)
|
||||||
}
|
}
|
||||||
@@ -272,6 +283,7 @@ impl Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "http1")]
|
#[cfg(feature = "http1")]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub(crate) fn new_user_header() -> Error {
|
pub(crate) fn new_user_header() -> Error {
|
||||||
Error::new_user(User::UnexpectedHeader)
|
Error::new_user(User::UnexpectedHeader)
|
||||||
}
|
}
|
||||||
@@ -289,6 +301,7 @@ impl Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "http1")]
|
#[cfg(feature = "http1")]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub(crate) fn new_user_unsupported_status_code() -> Error {
|
pub(crate) fn new_user_unsupported_status_code() -> Error {
|
||||||
Error::new_user(User::UnsupportedStatusCode)
|
Error::new_user(User::UnsupportedStatusCode)
|
||||||
}
|
}
|
||||||
@@ -309,6 +322,7 @@ impl Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub(crate) fn new_user_make_service<E: Into<Cause>>(cause: E) -> Error {
|
pub(crate) fn new_user_make_service<E: Into<Cause>>(cause: E) -> Error {
|
||||||
Error::new_user(User::MakeService).with(cause)
|
Error::new_user(User::MakeService).with(cause)
|
||||||
}
|
}
|
||||||
@@ -354,8 +368,10 @@ impl Error {
|
|||||||
Kind::Connect => "error trying to connect",
|
Kind::Connect => "error trying to connect",
|
||||||
Kind::Canceled => "operation was canceled",
|
Kind::Canceled => "operation was canceled",
|
||||||
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "tcp"))]
|
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "tcp"))]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
Kind::Listen => "error creating server listener",
|
Kind::Listen => "error creating server listener",
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
Kind::Accept => "error accepting connection",
|
Kind::Accept => "error accepting connection",
|
||||||
#[cfg(any(feature = "http1", feature = "http2", feature = "stream"))]
|
#[cfg(any(feature = "http1", feature = "http2", feature = "stream"))]
|
||||||
Kind::Body => "error reading a body from connection",
|
Kind::Body => "error reading a body from connection",
|
||||||
@@ -372,10 +388,12 @@ impl Error {
|
|||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
Kind::User(User::Body) => "error from user's HttpBody stream",
|
Kind::User(User::Body) => "error from user's HttpBody stream",
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
Kind::User(User::MakeService) => "error from user's MakeService",
|
Kind::User(User::MakeService) => "error from user's MakeService",
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
Kind::User(User::Service) => "error from user's Service",
|
Kind::User(User::Service) => "error from user's Service",
|
||||||
#[cfg(feature = "http1")]
|
#[cfg(feature = "http1")]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
Kind::User(User::UnexpectedHeader) => "user sent unexpected header",
|
Kind::User(User::UnexpectedHeader) => "user sent unexpected header",
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
#[cfg(feature = "client")]
|
#[cfg(feature = "client")]
|
||||||
@@ -384,6 +402,7 @@ impl Error {
|
|||||||
#[cfg(feature = "client")]
|
#[cfg(feature = "client")]
|
||||||
Kind::User(User::UnsupportedRequestMethod) => "request has unsupported HTTP method",
|
Kind::User(User::UnsupportedRequestMethod) => "request has unsupported HTTP method",
|
||||||
#[cfg(feature = "http1")]
|
#[cfg(feature = "http1")]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
Kind::User(User::UnsupportedStatusCode) => {
|
Kind::User(User::UnsupportedStatusCode) => {
|
||||||
"response has 1xx status code, not supported by server"
|
"response has 1xx status code, not supported by server"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ fn connection_has(value: &HeaderValue, needle: &str) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "http1")]
|
#[cfg(feature = "http1")]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub fn content_length_parse(value: &HeaderValue) -> Option<u64> {
|
pub fn content_length_parse(value: &HeaderValue) -> Option<u64> {
|
||||||
value.to_str().ok().and_then(|s| s.parse().ok())
|
value.to_str().ok().and_then(|s| s.parse().ok())
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/lib.rs
12
src/lib.rs
@@ -68,12 +68,9 @@ pub mod rt;
|
|||||||
pub mod service;
|
pub mod service;
|
||||||
pub mod upgrade;
|
pub mod upgrade;
|
||||||
|
|
||||||
cfg_any_http! {
|
cfg_proto! {
|
||||||
mod headers;
|
mod headers;
|
||||||
mod proto;
|
mod proto;
|
||||||
pub mod server;
|
|
||||||
|
|
||||||
pub use crate::server::Server;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_feature! {
|
cfg_feature! {
|
||||||
@@ -82,3 +79,10 @@ cfg_feature! {
|
|||||||
pub mod client;
|
pub mod client;
|
||||||
pub use crate::client::Client;
|
pub use crate::client::Client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg_feature! {
|
||||||
|
#![all(feature = "server", any(feature = "http1", feature = "http2"))]
|
||||||
|
|
||||||
|
pub mod server;
|
||||||
|
pub use crate::server::Server;
|
||||||
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub fn set_flush_pipeline(&mut self, enabled: bool) {
|
pub fn set_flush_pipeline(&mut self, enabled: bool) {
|
||||||
self.io.set_flush_pipeline(enabled);
|
self.io.set_flush_pipeline(enabled);
|
||||||
}
|
}
|
||||||
@@ -83,6 +84,7 @@ where
|
|||||||
self.state.title_case_headers = true;
|
self.state.title_case_headers = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub(crate) fn set_allow_half_close(&mut self) {
|
pub(crate) fn set_allow_half_close(&mut self) {
|
||||||
self.state.allow_half_close = true;
|
self.state.allow_half_close = true;
|
||||||
}
|
}
|
||||||
@@ -485,6 +487,7 @@ where
|
|||||||
Encode {
|
Encode {
|
||||||
head: &mut head,
|
head: &mut head,
|
||||||
body,
|
body,
|
||||||
|
#[cfg(feature = "server")]
|
||||||
keep_alive: self.state.wants_keep_alive(),
|
keep_alive: self.state.wants_keep_alive(),
|
||||||
req_method: &mut self.state.method,
|
req_method: &mut self.state.method,
|
||||||
title_case_headers: self.state.title_case_headers,
|
title_case_headers: self.state.title_case_headers,
|
||||||
@@ -690,6 +693,7 @@ where
|
|||||||
self.state.close_write();
|
self.state.close_write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub fn disable_keep_alive(&mut self) {
|
pub fn disable_keep_alive(&mut self) {
|
||||||
if self.state.is_idle() {
|
if self.state.is_idle() {
|
||||||
trace!("disable_keep_alive; closing idle connection");
|
trace!("disable_keep_alive; closing idle connection");
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
|
|
||||||
use bytes::{Buf, Bytes};
|
use bytes::{Buf, Bytes};
|
||||||
use http::{Request, StatusCode};
|
use http::Request;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite};
|
use tokio::io::{AsyncRead, AsyncWrite};
|
||||||
|
|
||||||
use super::{Http1Transaction, Wants};
|
use super::{Http1Transaction, Wants};
|
||||||
@@ -10,7 +10,6 @@ use crate::common::{task, Future, Pin, Poll, Unpin};
|
|||||||
use crate::proto::{
|
use crate::proto::{
|
||||||
BodyLength, Conn, Dispatched, MessageHead, RequestHead,
|
BodyLength, Conn, Dispatched, MessageHead, RequestHead,
|
||||||
};
|
};
|
||||||
use crate::service::HttpService;
|
|
||||||
|
|
||||||
pub(crate) struct Dispatcher<D, Bs: HttpBody, I, T> {
|
pub(crate) struct Dispatcher<D, Bs: HttpBody, I, T> {
|
||||||
conn: Conn<I, Bs::Data, T>,
|
conn: Conn<I, Bs::Data, T>,
|
||||||
@@ -34,10 +33,14 @@ pub(crate) trait Dispatch {
|
|||||||
fn should_poll(&self) -> bool;
|
fn should_poll(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg_server! {
|
||||||
|
use crate::service::HttpService;
|
||||||
|
|
||||||
pub struct Server<S: HttpService<B>, B> {
|
pub struct Server<S: HttpService<B>, B> {
|
||||||
in_flight: Pin<Box<Option<S::Future>>>,
|
in_flight: Pin<Box<Option<S::Future>>>,
|
||||||
pub(crate) service: S,
|
pub(crate) service: S,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cfg_client! {
|
cfg_client! {
|
||||||
#[pin_project::pin_project]
|
#[pin_project::pin_project]
|
||||||
@@ -74,6 +77,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub fn disable_keep_alive(&mut self) {
|
pub fn disable_keep_alive(&mut self) {
|
||||||
self.conn.disable_keep_alive();
|
self.conn.disable_keep_alive();
|
||||||
if self.conn.is_write_closed() {
|
if self.conn.is_write_closed() {
|
||||||
@@ -441,6 +445,7 @@ impl<'a, T> Drop for OptGuard<'a, T> {
|
|||||||
|
|
||||||
// ===== impl Server =====
|
// ===== impl Server =====
|
||||||
|
|
||||||
|
cfg_server! {
|
||||||
impl<S, B> Server<S, B>
|
impl<S, B> Server<S, B>
|
||||||
where
|
where
|
||||||
S: HttpService<B>,
|
S: HttpService<B>,
|
||||||
@@ -466,7 +471,7 @@ where
|
|||||||
S::Error: Into<Box<dyn StdError + Send + Sync>>,
|
S::Error: Into<Box<dyn StdError + Send + Sync>>,
|
||||||
Bs: HttpBody,
|
Bs: HttpBody,
|
||||||
{
|
{
|
||||||
type PollItem = MessageHead<StatusCode>;
|
type PollItem = MessageHead<http::StatusCode>;
|
||||||
type PollBody = Bs;
|
type PollBody = Bs;
|
||||||
type PollError = S::Error;
|
type PollError = S::Error;
|
||||||
type RecvItem = RequestHead;
|
type RecvItem = RequestHead;
|
||||||
@@ -521,6 +526,7 @@ where
|
|||||||
self.in_flight.is_some()
|
self.in_flight.is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ===== impl Client =====
|
// ===== impl Client =====
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ enum Kind {
|
|||||||
///
|
///
|
||||||
/// This is mostly only used with HTTP/1.0 with a length. This kind requires
|
/// This is mostly only used with HTTP/1.0 with a length. This kind requires
|
||||||
/// the connection to be closed when the body is finished.
|
/// the connection to be closed when the body is finished.
|
||||||
|
#[cfg(feature = "server")]
|
||||||
CloseDelimited,
|
CloseDelimited,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +62,7 @@ impl Encoder {
|
|||||||
Encoder::new(Kind::Length(len))
|
Encoder::new(Kind::Length(len))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub fn close_delimited() -> Encoder {
|
pub fn close_delimited() -> Encoder {
|
||||||
Encoder::new(Kind::CloseDelimited)
|
Encoder::new(Kind::CloseDelimited)
|
||||||
}
|
}
|
||||||
@@ -72,6 +74,7 @@ impl Encoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub fn set_last(mut self, is_last: bool) -> Self {
|
pub fn set_last(mut self, is_last: bool) -> Self {
|
||||||
self.is_last = is_last;
|
self.is_last = is_last;
|
||||||
self
|
self
|
||||||
@@ -83,6 +86,7 @@ impl Encoder {
|
|||||||
|
|
||||||
pub fn is_close_delimited(&self) -> bool {
|
pub fn is_close_delimited(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
|
#[cfg(feature = "server")]
|
||||||
Kind::CloseDelimited => true,
|
Kind::CloseDelimited => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
@@ -94,6 +98,7 @@ impl Encoder {
|
|||||||
Kind::Chunked => Ok(Some(EncodedBuf {
|
Kind::Chunked => Ok(Some(EncodedBuf {
|
||||||
kind: BufKind::ChunkedEnd(b"0\r\n\r\n"),
|
kind: BufKind::ChunkedEnd(b"0\r\n\r\n"),
|
||||||
})),
|
})),
|
||||||
|
#[cfg(feature = "server")]
|
||||||
Kind::CloseDelimited => Ok(None),
|
Kind::CloseDelimited => Ok(None),
|
||||||
Kind::Length(_) => Err(NotEof),
|
Kind::Length(_) => Err(NotEof),
|
||||||
}
|
}
|
||||||
@@ -125,6 +130,7 @@ impl Encoder {
|
|||||||
BufKind::Exact(msg)
|
BufKind::Exact(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "server")]
|
||||||
Kind::CloseDelimited => {
|
Kind::CloseDelimited => {
|
||||||
trace!("close delimited write {}B", len);
|
trace!("close delimited write {}B", len);
|
||||||
BufKind::Exact(msg)
|
BufKind::Exact(msg)
|
||||||
@@ -168,6 +174,7 @@ impl Encoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "server")]
|
||||||
Kind::CloseDelimited => {
|
Kind::CloseDelimited => {
|
||||||
trace!("close delimited write {}B", len);
|
trace!("close delimited write {}B", len);
|
||||||
dst.buffer(msg);
|
dst.buffer(msg);
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub fn set_flush_pipeline(&mut self, enabled: bool) {
|
pub fn set_flush_pipeline(&mut self, enabled: bool) {
|
||||||
debug_assert!(!self.write_buf.has_remaining());
|
debug_assert!(!self.write_buf.has_remaining());
|
||||||
self.flush_pipeline = enabled;
|
self.flush_pipeline = enabled;
|
||||||
|
|||||||
@@ -18,12 +18,15 @@ mod encode;
|
|||||||
mod io;
|
mod io;
|
||||||
mod role;
|
mod role;
|
||||||
|
|
||||||
pub(crate) type ServerTransaction = role::Server;
|
|
||||||
|
|
||||||
cfg_client! {
|
cfg_client! {
|
||||||
pub(crate) type ClientTransaction = role::Client;
|
pub(crate) type ClientTransaction = role::Client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg_server! {
|
||||||
|
pub(crate) type ServerTransaction = role::Server;
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) trait Http1Transaction {
|
pub(crate) trait Http1Transaction {
|
||||||
type Incoming;
|
type Incoming;
|
||||||
type Outgoing: Default;
|
type Outgoing: Default;
|
||||||
@@ -73,6 +76,7 @@ pub(crate) struct ParseContext<'a> {
|
|||||||
pub(crate) struct Encode<'a, T> {
|
pub(crate) struct Encode<'a, T> {
|
||||||
head: &'a mut MessageHead<T>,
|
head: &'a mut MessageHead<T>,
|
||||||
body: Option<BodyLength>,
|
body: Option<BodyLength>,
|
||||||
|
#[cfg(feature = "server")]
|
||||||
keep_alive: bool,
|
keep_alive: bool,
|
||||||
req_method: &'a mut Option<Method>,
|
req_method: &'a mut Option<Method>,
|
||||||
title_case_headers: bool,
|
title_case_headers: bool,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use http::header::{self, Entry, HeaderName, HeaderValue};
|
|||||||
use http::{HeaderMap, Method, StatusCode, Version};
|
use http::{HeaderMap, Method, StatusCode, Version};
|
||||||
|
|
||||||
use crate::body::DecodedLength;
|
use crate::body::DecodedLength;
|
||||||
|
#[cfg(feature = "server")]
|
||||||
use crate::common::date;
|
use crate::common::date;
|
||||||
use crate::error::Parse;
|
use crate::error::Parse;
|
||||||
use crate::headers;
|
use crate::headers;
|
||||||
@@ -94,10 +95,13 @@ where
|
|||||||
|
|
||||||
// There are 2 main roles, Client and Server.
|
// There are 2 main roles, Client and Server.
|
||||||
|
|
||||||
|
#[cfg(feature = "client")]
|
||||||
pub(crate) enum Client {}
|
pub(crate) enum Client {}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub(crate) enum Server {}
|
pub(crate) enum Server {}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
impl Http1Transaction for Server {
|
impl Http1Transaction for Server {
|
||||||
type Incoming = RequestLine;
|
type Incoming = RequestLine;
|
||||||
type Outgoing = StatusCode;
|
type Outgoing = StatusCode;
|
||||||
@@ -618,6 +622,7 @@ impl Http1Transaction for Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
impl Server {
|
impl Server {
|
||||||
fn can_have_body(method: &Option<Method>, status: StatusCode) -> bool {
|
fn can_have_body(method: &Option<Method>, status: StatusCode) -> bool {
|
||||||
Server::can_chunked(method, status)
|
Server::can_chunked(method, status)
|
||||||
@@ -640,6 +645,7 @@ impl Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "client")]
|
||||||
impl Http1Transaction for Client {
|
impl Http1Transaction for Client {
|
||||||
type Incoming = StatusCode;
|
type Incoming = StatusCode;
|
||||||
type Outgoing = RequestLine;
|
type Outgoing = RequestLine;
|
||||||
@@ -779,6 +785,7 @@ impl Http1Transaction for Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "client")]
|
||||||
impl Client {
|
impl Client {
|
||||||
/// Returns Some(length, wants_upgrade) if successful.
|
/// Returns Some(length, wants_upgrade) if successful.
|
||||||
///
|
///
|
||||||
@@ -846,9 +853,6 @@ impl Client {
|
|||||||
Ok(Some((DecodedLength::CLOSE_DELIMITED, false)))
|
Ok(Some((DecodedLength::CLOSE_DELIMITED, false)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Client {
|
|
||||||
fn set_length(head: &mut RequestHead, body: Option<BodyLength>) -> Encoder {
|
fn set_length(head: &mut RequestHead, body: Option<BodyLength>) -> Encoder {
|
||||||
let body = if let Some(body) = body {
|
let body = if let Some(body) = body {
|
||||||
body
|
body
|
||||||
|
|||||||
@@ -14,14 +14,16 @@ use crate::common::{task, Future, Pin, Poll};
|
|||||||
use crate::headers::content_length_parse_all;
|
use crate::headers::content_length_parse_all;
|
||||||
|
|
||||||
pub(crate) mod ping;
|
pub(crate) mod ping;
|
||||||
pub(crate) mod server;
|
|
||||||
|
|
||||||
cfg_client! {
|
cfg_client! {
|
||||||
pub(crate) mod client;
|
pub(crate) mod client;
|
||||||
pub(crate) use self::client::ClientTask;
|
pub(crate) use self::client::ClientTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg_server! {
|
||||||
|
pub(crate) mod server;
|
||||||
pub(crate) use self::server::Server;
|
pub(crate) use self::server::Server;
|
||||||
|
}
|
||||||
|
|
||||||
/// Default initial stream window size defined in HTTP2 spec.
|
/// Default initial stream window size defined in HTTP2 spec.
|
||||||
pub(crate) const SPEC_WINDOW_SIZE: u32 = 65_535;
|
pub(crate) const SPEC_WINDOW_SIZE: u32 = 65_535;
|
||||||
|
|||||||
@@ -3,10 +3,12 @@
|
|||||||
cfg_http1! {
|
cfg_http1! {
|
||||||
pub(crate) mod h1;
|
pub(crate) mod h1;
|
||||||
|
|
||||||
pub(crate) use self::h1::{Conn, ServerTransaction};
|
pub(crate) use self::h1::Conn;
|
||||||
|
|
||||||
#[cfg(feature = "client")]
|
#[cfg(feature = "client")]
|
||||||
pub(crate) use self::h1::dispatch;
|
pub(crate) use self::h1::dispatch;
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
pub(crate) use self::h1::ServerTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_http2! {
|
cfg_http2! {
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ pub(crate) use self::http::HttpService;
|
|||||||
#[cfg(feature = "client")]
|
#[cfg(feature = "client")]
|
||||||
pub(crate) use self::make::MakeConnection;
|
pub(crate) use self::make::MakeConnection;
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
|
#[cfg(feature = "server")]
|
||||||
pub(crate) use self::make::MakeServiceRef;
|
pub(crate) use self::make::MakeServiceRef;
|
||||||
#[cfg(any(feature = "http1", feature = "http2"))]
|
#[cfg(any(feature = "http1", feature = "http2"))]
|
||||||
#[cfg(feature = "client")]
|
#[cfg(feature = "client")]
|
||||||
|
|||||||
Reference in New Issue
Block a user