1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-06-12 02:09:36 +00:00
actix-web/actix-http/src/client/connection.rs

289 lines
7.6 KiB
Rust
Raw Normal View History

2019-03-28 01:53:19 +00:00
use std::{fmt, io, time};
2018-11-12 07:12:54 +00:00
2019-03-28 01:53:19 +00:00
use actix_codec::{AsyncRead, AsyncWrite, Framed};
use bytes::{Buf, Bytes};
use futures::future::{err, Either, Future, FutureResult};
use futures::Poll;
2019-01-29 04:41:09 +00:00
use h2::client::SendRequest;
2018-11-12 07:12:54 +00:00
2019-01-29 04:41:09 +00:00
use crate::body::MessageBody;
2019-03-28 01:53:19 +00:00
use crate::h1::ClientCodec;
use crate::message::{RequestHeadType, ResponseHead};
use crate::payload::Payload;
2019-01-29 04:41:09 +00:00
use super::error::SendRequestError;
2019-04-08 18:09:57 +00:00
use super::pool::{Acquired, Protocol};
2019-01-29 04:41:09 +00:00
use super::{h1proto, h2proto};
pub(crate) enum ConnectionType<Io> {
H1(Io),
H2(SendRequest<Bytes>),
}
2019-01-29 18:34:27 +00:00
pub trait Connection {
2019-03-28 01:53:19 +00:00
type Io: AsyncRead + AsyncWrite;
type Future: Future<Item = (ResponseHead, Payload), Error = SendRequestError>;
2019-01-29 04:41:09 +00:00
2019-04-08 18:09:57 +00:00
fn protocol(&self) -> Protocol;
2019-03-26 04:52:45 +00:00
/// Send request and body
fn send_request<B: MessageBody + 'static, H: Into<RequestHeadType>>(
2019-01-29 04:41:09 +00:00
self,
head: H,
2019-01-29 04:41:09 +00:00
body: B,
) -> Self::Future;
2019-03-28 01:53:19 +00:00
type TunnelFuture: Future<
Item = (ResponseHead, Framed<Self::Io, ClientCodec>),
Error = SendRequestError,
>;
/// Send request, returns Response and Framed
fn open_tunnel<H: Into<RequestHeadType>>(self, head: H) -> Self::TunnelFuture;
2019-01-29 04:41:09 +00:00
}
2018-11-12 07:12:54 +00:00
2019-01-29 04:41:09 +00:00
pub(crate) trait ConnectionLifetime: AsyncRead + AsyncWrite + 'static {
2018-11-15 19:10:23 +00:00
/// Close connection
fn close(&mut self);
/// Release connection to the connection pool
fn release(&mut self);
}
#[doc(hidden)]
2018-11-12 07:12:54 +00:00
/// HTTP client connection
2018-11-15 19:10:23 +00:00
pub struct IoConnection<T> {
2019-01-29 04:41:09 +00:00
io: Option<ConnectionType<T>>,
2018-11-12 07:12:54 +00:00
created: time::Instant,
pool: Option<Acquired<T>>,
}
2018-11-15 19:10:23 +00:00
impl<T> fmt::Debug for IoConnection<T>
2018-11-12 07:12:54 +00:00
where
2018-11-14 06:53:30 +00:00
T: fmt::Debug,
2018-11-12 07:12:54 +00:00
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2019-01-29 04:41:09 +00:00
match self.io {
Some(ConnectionType::H1(ref io)) => write!(f, "H1Connection({:?})", io),
Some(ConnectionType::H2(_)) => write!(f, "H2Connection"),
None => write!(f, "Connection(Empty)"),
}
2018-11-12 07:12:54 +00:00
}
}
2019-04-04 17:59:34 +00:00
impl<T: AsyncRead + AsyncWrite> IoConnection<T> {
2019-01-29 04:41:09 +00:00
pub(crate) fn new(
io: ConnectionType<T>,
created: time::Instant,
pool: Option<Acquired<T>>,
) -> Self {
2018-11-15 19:10:23 +00:00
IoConnection {
2019-01-29 04:41:09 +00:00
pool,
2018-11-12 07:12:54 +00:00
created,
2018-11-15 19:10:23 +00:00
io: Some(io),
2018-11-12 07:12:54 +00:00
}
}
2019-01-29 04:41:09 +00:00
pub(crate) fn into_inner(self) -> (ConnectionType<T>, time::Instant) {
2018-11-15 19:10:23 +00:00
(self.io.unwrap(), self.created)
}
}
2019-01-29 18:34:27 +00:00
impl<T> Connection for IoConnection<T>
2019-01-29 04:41:09 +00:00
where
T: AsyncRead + AsyncWrite + 'static,
{
2019-03-28 01:53:19 +00:00
type Io = T;
type Future =
Box<dyn Future<Item = (ResponseHead, Payload), Error = SendRequestError>>;
2019-01-29 04:41:09 +00:00
2019-04-08 18:09:57 +00:00
fn protocol(&self) -> Protocol {
match self.io {
Some(ConnectionType::H1(_)) => Protocol::Http1,
Some(ConnectionType::H2(_)) => Protocol::Http2,
None => Protocol::Http1,
}
}
fn send_request<B: MessageBody + 'static, H: Into<RequestHeadType>>(
2019-01-29 04:41:09 +00:00
mut self,
head: H,
2019-01-29 04:41:09 +00:00
body: B,
) -> Self::Future {
match self.io.take().unwrap() {
ConnectionType::H1(io) => Box::new(h1proto::send_request(
io,
head.into(),
2019-01-29 04:41:09 +00:00
body,
self.created,
self.pool,
)),
ConnectionType::H2(io) => Box::new(h2proto::send_request(
io,
head.into(),
2019-01-29 04:41:09 +00:00
body,
self.created,
self.pool,
)),
2018-11-12 07:12:54 +00:00
}
}
2019-03-28 01:53:19 +00:00
type TunnelFuture = Either<
Box<
2019-07-17 09:48:37 +00:00
dyn Future<
2019-03-28 01:53:19 +00:00
Item = (ResponseHead, Framed<Self::Io, ClientCodec>),
Error = SendRequestError,
>,
>,
FutureResult<(ResponseHead, Framed<Self::Io, ClientCodec>), SendRequestError>,
>;
/// Send request, returns Response and Framed
fn open_tunnel<H: Into<RequestHeadType>>(mut self, head: H) -> Self::TunnelFuture {
2019-03-28 01:53:19 +00:00
match self.io.take().unwrap() {
ConnectionType::H1(io) => {
Either::A(Box::new(h1proto::open_tunnel(io, head.into())))
2019-03-28 01:53:19 +00:00
}
ConnectionType::H2(io) => {
if let Some(mut pool) = self.pool.take() {
pool.release(IoConnection::new(
ConnectionType::H2(io),
self.created,
None,
));
}
Either::B(err(SendRequestError::TunnelNotSupported))
}
}
}
2018-11-12 07:12:54 +00:00
}
2019-01-29 04:41:09 +00:00
#[allow(dead_code)]
pub(crate) enum EitherConnection<A, B> {
A(IoConnection<A>),
B(IoConnection<B>),
2018-11-12 07:12:54 +00:00
}
2019-01-29 18:34:27 +00:00
impl<A, B> Connection for EitherConnection<A, B>
2019-01-29 04:41:09 +00:00
where
A: AsyncRead + AsyncWrite + 'static,
B: AsyncRead + AsyncWrite + 'static,
{
2019-03-28 01:53:19 +00:00
type Io = EitherIo<A, B>;
type Future =
Box<dyn Future<Item = (ResponseHead, Payload), Error = SendRequestError>>;
2019-01-29 04:41:09 +00:00
2019-04-08 18:09:57 +00:00
fn protocol(&self) -> Protocol {
match self {
EitherConnection::A(con) => con.protocol(),
EitherConnection::B(con) => con.protocol(),
}
}
fn send_request<RB: MessageBody + 'static, H: Into<RequestHeadType>>(
2019-01-29 04:41:09 +00:00
self,
head: H,
2019-01-29 04:41:09 +00:00
body: RB,
) -> Self::Future {
match self {
EitherConnection::A(con) => con.send_request(head, body),
EitherConnection::B(con) => con.send_request(head, body),
}
2018-11-12 07:12:54 +00:00
}
2019-03-28 01:53:19 +00:00
type TunnelFuture = Box<
2019-07-17 09:48:37 +00:00
dyn Future<
2019-03-28 01:53:19 +00:00
Item = (ResponseHead, Framed<Self::Io, ClientCodec>),
Error = SendRequestError,
>,
>;
/// Send request, returns Response and Framed
fn open_tunnel<H: Into<RequestHeadType>>(self, head: H) -> Self::TunnelFuture {
2019-03-28 01:53:19 +00:00
match self {
EitherConnection::A(con) => Box::new(
con.open_tunnel(head)
2019-03-30 04:13:39 +00:00
.map(|(head, framed)| (head, framed.map_io(EitherIo::A))),
2019-03-28 01:53:19 +00:00
),
EitherConnection::B(con) => Box::new(
con.open_tunnel(head)
2019-03-30 04:13:39 +00:00
.map(|(head, framed)| (head, framed.map_io(EitherIo::B))),
2019-03-28 01:53:19 +00:00
),
}
}
}
pub enum EitherIo<A, B> {
A(A),
B(B),
}
impl<A, B> io::Read for EitherIo<A, B>
where
A: io::Read,
B: io::Read,
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self {
EitherIo::A(ref mut val) => val.read(buf),
EitherIo::B(ref mut val) => val.read(buf),
}
}
}
impl<A, B> AsyncRead for EitherIo<A, B>
where
A: AsyncRead,
B: AsyncRead,
{
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
match self {
EitherIo::A(ref val) => val.prepare_uninitialized_buffer(buf),
EitherIo::B(ref val) => val.prepare_uninitialized_buffer(buf),
}
}
}
impl<A, B> io::Write for EitherIo<A, B>
where
A: io::Write,
B: io::Write,
{
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match self {
EitherIo::A(ref mut val) => val.write(buf),
EitherIo::B(ref mut val) => val.write(buf),
}
}
fn flush(&mut self) -> io::Result<()> {
match self {
EitherIo::A(ref mut val) => val.flush(),
EitherIo::B(ref mut val) => val.flush(),
}
}
}
impl<A, B> AsyncWrite for EitherIo<A, B>
where
A: AsyncWrite,
B: AsyncWrite,
{
fn shutdown(&mut self) -> Poll<(), io::Error> {
match self {
EitherIo::A(ref mut val) => val.shutdown(),
EitherIo::B(ref mut val) => val.shutdown(),
}
}
fn write_buf<U: Buf>(&mut self, buf: &mut U) -> Poll<usize, io::Error>
where
Self: Sized,
{
match self {
EitherIo::A(ref mut val) => val.write_buf(buf),
EitherIo::B(ref mut val) => val.write_buf(buf),
}
}
2018-11-12 07:12:54 +00:00
}