From 6de0b4d26fd82b4d1303080b0ba8c4db2d4f0fd1 Mon Sep 17 00:00:00 2001 From: Lucio Franco Date: Mon, 20 Jan 2020 11:21:44 -0500 Subject: [PATCH] fix(transport): Use Uri host if no domain for tls (#244) * fix(transport): Use Uri host if no domain for tls * Fix warnings --- tonic/src/transport/channel/tls.rs | 3 +- tonic/src/transport/error.rs | 76 +++++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/tonic/src/transport/channel/tls.rs b/tonic/src/transport/channel/tls.rs index 8a44cff14..33d8f83c5 100644 --- a/tonic/src/transport/channel/tls.rs +++ b/tonic/src/transport/channel/tls.rs @@ -1,6 +1,7 @@ use crate::transport::{ service::TlsConnector, tls::{Certificate, Identity}, + Error, }; use http::Uri; use std::fmt; @@ -81,7 +82,7 @@ impl ClientTlsConfig { pub(crate) fn tls_connector(&self, uri: Uri) -> Result { let domain = match &self.domain { - None => uri.to_string(), + None => uri.host().ok_or(Error::new_invalid_uri())?.to_string(), Some(domain) => domain.clone(), }; match &self.rustls_raw { diff --git a/tonic/src/transport/error.rs b/tonic/src/transport/error.rs index 77c84a61e..584164080 100644 --- a/tonic/src/transport/error.rs +++ b/tonic/src/transport/error.rs @@ -1,23 +1,85 @@ -use std::{error, fmt}; +// TODO: remove this when we use errors throughout, +// there are some that are only used under the TLS feature +// these probably should be scoped to a `TLSError` enum. +#![allow(dead_code)] + +use std::{error::Error as StdError, fmt}; + +type Source = Box; /// Error's that originate from the client or server; +pub struct Error { + inner: ErrorImpl, +} + +struct ErrorImpl { + kind: Kind, + source: Option, +} + #[derive(Debug)] -pub struct Error(crate::Error); +pub(crate) enum Kind { + Transport, + InvalidUri, +} impl Error { + pub(crate) fn new(kind: Kind) -> Self { + Self { + inner: ErrorImpl { kind, source: None }, + } + } + + pub(crate) fn with(mut self, source: impl Into) -> Self { + self.inner.source = Some(source.into()); + self + } + pub(crate) fn from_source(source: impl Into) -> Self { - Self(source.into()) + Error::new(Kind::Transport).with(source) + } + + pub(crate) fn new_invalid_uri() -> Self { + Error::new(Kind::InvalidUri) + } + + fn description(&self) -> &str { + match &self.inner.kind { + Kind::Transport => "transport error", + Kind::InvalidUri => "invalid URI", + } + } +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut f = f.debug_tuple("tonic::transport::Error"); + + f.field(&self.inner.kind); + + if let Some(source) = &self.inner.source { + f.field(source); + } + + f.finish() } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) + if let Some(source) = &self.inner.source { + write!(f, "{}: {}", self.description(), source) + } else { + f.write_str(self.description()) + } } } -impl error::Error for Error { - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - self.0.source() +impl StdError for Error { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + self.inner + .source + .as_ref() + .map(|source| &**source as &(dyn StdError + 'static)) } }