mirror of
https://github.com/SergioBenitez/Rocket.git
synced 2026-02-06 10:48:05 +00:00
Expose the SNI when possible. (#2943)
Grabs the SNI from TLS connections and saves to ConenctionMeta struct. Provides useful methods for exracting the SNI from requests. Closes #2942
This commit is contained in:
parent
3ccfd8bd77
commit
3d1de7bac5
8
.editorconfig
Normal file
8
.editorconfig
Normal file
@ -0,0 +1,8 @@
|
||||
root = true
|
||||
|
||||
[*.rs]
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
tab_width = 4
|
||||
@ -22,6 +22,8 @@ pub trait Connection: AsyncRead + AsyncWrite + Send + Unpin {
|
||||
/// Defaults to an empty vector to indicate that no certificates were
|
||||
/// presented.
|
||||
fn certificates(&self) -> Option<Certificates<'_>> { None }
|
||||
|
||||
fn server_name(&self) -> Option<&str> { None }
|
||||
}
|
||||
|
||||
impl<A: Connection, B: Connection> Connection for Either<A, B> {
|
||||
|
||||
@ -45,13 +45,19 @@ pub(crate) struct ConnectionMeta {
|
||||
pub peer_endpoint: Option<Endpoint>,
|
||||
#[cfg_attr(not(feature = "mtls"), allow(dead_code))]
|
||||
pub peer_certs: Option<Arc<Certificates<'static>>>,
|
||||
#[cfg_attr(feature = "tls", allow(dead_code))]
|
||||
pub server_name: Option<String>,
|
||||
}
|
||||
|
||||
impl ConnectionMeta {
|
||||
pub fn new(endpoint: io::Result<Endpoint>, certs: Option<Certificates<'_>>) -> Self {
|
||||
pub fn new(
|
||||
endpoint: io::Result<Endpoint>,
|
||||
certs: Option<Certificates<'_>>,
|
||||
server_name: Option<&str>) -> Self {
|
||||
ConnectionMeta {
|
||||
peer_endpoint: endpoint.ok(),
|
||||
peer_certs: certs.map(|c| c.into_owned()).map(Arc::new),
|
||||
server_name: server_name.map(|s| s.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -295,6 +301,16 @@ impl<'r> Request<'r> {
|
||||
self.state.host.as_ref()
|
||||
}
|
||||
|
||||
/// Returns the resolved SNI server name requested in the TLS handshake, if
|
||||
/// any.
|
||||
///
|
||||
/// Ideally, this will match the `Host` header in the request.
|
||||
#[cfg(feature = "tls")]
|
||||
#[inline(always)]
|
||||
pub fn sni(&mut self) -> Option<&str> {
|
||||
self.connection.server_name.as_deref()
|
||||
}
|
||||
|
||||
/// Sets the host of `self` to `host`.
|
||||
///
|
||||
/// # Example
|
||||
|
||||
@ -172,7 +172,11 @@ impl Rocket<Orbit> {
|
||||
let (listener, rocket, server) = (listener.clone(), self.clone(), server.clone());
|
||||
spawn_inspect(|e| log_server_error(&**e), async move {
|
||||
let conn = listener.connect(accept).race_io(rocket.shutdown()).await?;
|
||||
let meta = ConnectionMeta::new(conn.endpoint(), conn.certificates());
|
||||
let meta = ConnectionMeta::new(
|
||||
conn.endpoint(),
|
||||
conn.certificates(),
|
||||
conn.server_name()
|
||||
);
|
||||
let service = service_fn(|mut req| {
|
||||
let upgrade = hyper::upgrade::on(&mut req);
|
||||
let (parts, incoming) = req.into_parts();
|
||||
@ -205,7 +209,7 @@ impl Rocket<Orbit> {
|
||||
while let Some(mut conn) = stream.accept().race_io(rocket.shutdown()).await? {
|
||||
let rocket = rocket.clone();
|
||||
spawn_inspect(|e: &io::Error| log_server_error(e), async move {
|
||||
let meta = ConnectionMeta::new(conn.endpoint(), None);
|
||||
let meta = ConnectionMeta::new(conn.endpoint(), None, None);
|
||||
let rx = conn.rx.cancellable(rocket.shutdown.clone());
|
||||
let response = rocket.clone()
|
||||
.service(conn.parts, rx, None, meta)
|
||||
|
||||
@ -96,4 +96,13 @@ impl<C: Connection> Connection for TlsStream<C> {
|
||||
#[cfg(not(feature = "mtls"))]
|
||||
None
|
||||
}
|
||||
|
||||
fn server_name(&self) -> Option<&str> {
|
||||
#[cfg(feature = "tls")] {
|
||||
self.get_ref().1.server_name()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "tls"))]
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user