From 6a461dbb2365fd92f184e4e6e52fdb3b9964f37b Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Tue, 9 Nov 2021 00:01:10 +0800 Subject: [PATCH] make awc support http2 over plain tcp --- awc/Cargo.toml | 5 ++++ awc/src/client/connector.rs | 60 ++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/awc/Cargo.toml b/awc/Cargo.toml index c40621597..f26696514 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -52,6 +52,11 @@ trust-dns = ["trust-dns-resolver"] # Don't rely on these whatsoever. They may disappear at anytime. __compress = [] +# Enable dangerous feature for testing and local network usage: +# - HTTP/2 over TCP(No Tls). +# DO NOT enable this over any internet use case. +dangerous = [] + [dependencies] actix-codec = "0.4.1" actix-service = "2.0.0" diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index 8a162c4f8..f5d313ea7 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -279,7 +279,65 @@ where }; let tls_service = match self.ssl { - SslConnector::None => None, + SslConnector::None => { + #[cfg(not(feature = "dangerous"))] + { + None + } + #[cfg(feature = "dangerous")] + { + /* + With dangerous feature enabled Connector would use a NoOp Tls connection service that + pass through plain TCP as Tls connection. + + The Protocol version of this fake Tls connection is set to be HTTP2. + */ + + impl IntoConnectionIo for TcpConnection> { + fn into_connection_io(self) -> (Box, Protocol) { + let io = self.into_parts().0; + (io, Protocol::Http2) + } + } + + #[derive(Clone)] + struct NoOpTlsConnectorService; + + use actix_tls::connect::Connection; + use std::{ + future::{ready, Ready}, + io, + }; + + impl Service> for NoOpTlsConnectorService + where + U: ActixStream + 'static, + { + type Response = Connection>; + type Error = io::Error; + type Future = Ready>; + + actix_service::always_ready!(); + + fn call(&self, connection: Connection) -> Self::Future { + let (io, connection) = connection.replace_io(()); + let (_, connection) = connection.replace_io(Box::new(io) as _); + + ready(Ok(connection)) + } + } + + let handshake_timeout = self.config.handshake_timeout; + + let tls_service = TlsConnectorService { + tcp_service: tcp_service_inner, + tls_service: NoOpTlsConnectorService, + timeout: handshake_timeout, + }; + + Some(actix_service::boxed::rc_service(tls_service)) + } + } #[cfg(feature = "openssl")] SslConnector::Openssl(tls) => { const H2: &[u8] = b"h2";