-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathhttp_version.rs
More file actions
80 lines (67 loc) · 2.37 KB
/
http_version.rs
File metadata and controls
80 lines (67 loc) · 2.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//! HTTP Version support and negotiation
use hyper::Response;
use std::future::Future;
use std::pin::Pin;
pub const ALPN_H2: &[u8] = b"h2";
pub const ALPN_HTTP11: &[u8] = b"http/1.1";
/// Supported HTTP versions
#[derive(Debug)]
pub enum HttpVersion {
/// HTTP 1.1
Http1,
/// HTTP 2
Http2,
}
impl HttpVersion {
/// Given a server TLS stream, choose an HTTP version to use
pub fn from_negotiated_protocol_server<IO>(tls: &tokio_rustls::server::TlsStream<IO>) -> Self {
let (_io, conn) = tls.get_ref();
let chosen_protocol = Self::from_alpn_bytes(conn.alpn_protocol());
tracing::debug!("[server] Chosen protocol {chosen_protocol:?}",);
chosen_protocol
}
/// Given a client TLS stream, choose an HTTP version to use
pub fn from_negotiated_protocol_client<IO>(tls: &tokio_rustls::client::TlsStream<IO>) -> Self {
let (_io, conn) = tls.get_ref();
let chosen_protocol = Self::from_alpn_bytes(conn.alpn_protocol());
tracing::debug!("[client] Chosen protocol {chosen_protocol:?}",);
chosen_protocol
}
fn from_alpn_bytes(chosen_protocol: Option<&[u8]>) -> Self {
match chosen_protocol {
Some(p) if p.ends_with(ALPN_H2) => HttpVersion::Http2,
Some(p) if p.ends_with(ALPN_HTTP11) => HttpVersion::Http1,
_ => HttpVersion::Http1,
}
}
}
type Http1Sender = hyper::client::conn::http1::SendRequest<hyper::body::Incoming>;
type Http2Sender = hyper::client::conn::http2::SendRequest<hyper::body::Incoming>;
/// A protocol version agnostic HTTP sender
pub enum HttpSender {
Http1(Http1Sender),
Http2(Http2Sender),
}
impl From<Http1Sender> for HttpSender {
fn from(inner: Http1Sender) -> Self {
Self::Http1(inner)
}
}
impl From<Http2Sender> for HttpSender {
fn from(inner: Http2Sender) -> Self {
Self::Http2(inner)
}
}
impl HttpSender {
pub async fn send_request(
&mut self,
request: http::Request<hyper::body::Incoming>,
) -> Result<Response<hyper::body::Incoming>, hyper::Error> {
match self {
Self::Http1(sender) => sender.send_request(request).await,
Self::Http2(sender) => sender.send_request(request).await,
}
}
}
/// A protocol version agnostic HTTP connection future
pub type HttpConnection = Pin<Box<dyn Future<Output = Result<(), hyper::Error>> + Send>>;