Add specific URL error types

pull/168/head
WiredSound 4 years ago
parent 7265a8560c
commit 34c6e63d87
  1. 14
      src/client.rs
  2. 34
      src/error.rs
  3. 8
      src/handshake/client.rs

@ -52,7 +52,7 @@ mod encryption {
use std::net::TcpStream;
use crate::{
error::{Error, Result},
error::{Error, UrlErrorType, Result},
stream::Mode,
};
@ -62,7 +62,7 @@ mod encryption {
pub fn wrap_stream(stream: TcpStream, _domain: &str, mode: Mode) -> Result<AutoStream> {
match mode {
Mode::Plain => Ok(stream),
Mode::Tls => Err(Error::Url("TLS support not compiled in.".into())),
Mode::Tls => Err(Error::Url(UrlErrorType::TlsFeatureNotEnabled)),
}
}
}
@ -71,7 +71,7 @@ use self::encryption::wrap_stream;
pub use self::encryption::AutoStream;
use crate::{
error::{Error, Result},
error::{Error, UrlErrorType, Result},
handshake::{client::ClientHandshake, HandshakeError},
protocol::WebSocket,
stream::{Mode, NoDelay},
@ -104,7 +104,7 @@ pub fn connect_with_config<Req: IntoClientRequest>(
let uri = request.uri();
let mode = uri_mode(uri)?;
let host =
request.uri().host().ok_or_else(|| Error::Url("No host name in the URL".into()))?;
request.uri().host().ok_or_else(|| Error::Url(UrlErrorType::NoHostName))?;
let port = uri.port_u16().unwrap_or(match mode {
Mode::Plain => 80,
Mode::Tls => 443,
@ -166,7 +166,7 @@ pub fn connect<Req: IntoClientRequest>(request: Req) -> Result<(WebSocket<AutoSt
}
fn connect_to_some(addrs: &[SocketAddr], uri: &Uri, mode: Mode) -> Result<AutoStream> {
let domain = uri.host().ok_or_else(|| Error::Url("No host name in the URL".into()))?;
let domain = uri.host().ok_or_else(|| Error::Url(UrlErrorType::NoHostName))?;
for addr in addrs {
debug!("Trying to contact {} at {}...", uri, addr);
if let Ok(raw_stream) = TcpStream::connect(addr) {
@ -175,7 +175,7 @@ fn connect_to_some(addrs: &[SocketAddr], uri: &Uri, mode: Mode) -> Result<AutoSt
}
}
}
Err(Error::Url(format!("Unable to connect to {}", uri).into()))
Err(Error::Url(UrlErrorType::UnableToConnect(uri.to_string())))
}
/// Get the mode of the given URL.
@ -186,7 +186,7 @@ pub fn uri_mode(uri: &Uri) -> Result<Mode> {
match uri.scheme_str() {
Some("ws") => Ok(Mode::Plain),
Some("wss") => Ok(Mode::Tls),
_ => Err(Error::Url("URL scheme not supported".into())),
_ => Err(Error::Url(UrlErrorType::UnsupportedUrlScheme)),
}
}

@ -14,7 +14,7 @@ pub mod tls {
/// Result type of all Tungstenite library calls.
pub type Result<T> = result::Result<T, Error>;
/// Possible WebSocket errors
/// Possible WebSocket errors.
#[derive(Debug)]
pub enum Error {
/// WebSocket connection closed normally. This informs you of the close.
@ -54,7 +54,7 @@ pub enum Error {
/// UTF coding error
Utf8,
/// Invalid URL.
Url(Cow<'static, str>),
Url(UrlErrorType),
/// HTTP error.
Http(Response<Option<String>>),
/// HTTP format error.
@ -151,3 +151,33 @@ impl From<httparse::Error> for Error {
}
}
}
/// Indicates the specific type/cause of URL error.
#[derive(Debug)]
pub enum UrlErrorType {
/// TLS is used despite not being compiled with the TLS feature enabled.
TlsFeatureNotEnabled,
/// The URL does not include a host name.
NoHostName,
/// Failed to connect with this URL.
UnableToConnect(String),
/// Unsupported URL scheme used (only `ws://` or `wss://` may be used).
UnsupportedUrlScheme,
/// The URL host name, though included, is empty.
EmptyHostName,
/// The URL does not include a path/query.
NoPathOrQuery
}
impl fmt::Display for UrlErrorType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
UrlErrorType::TlsFeatureNotEnabled => write!(f, "TLS support not compiled in"),
UrlErrorType::NoHostName => write!(f, "No host name in the URL"),
UrlErrorType::UnableToConnect(uri) => write!(f, "Unable to connect to {}", uri),
UrlErrorType::UnsupportedUrlScheme => write!(f, "URL scheme not supported"),
UrlErrorType::EmptyHostName => write!(f, "URL contains empty host name"),
UrlErrorType::NoPathOrQuery => write!(f, "No path/query in URL")
}
}
}

@ -16,7 +16,7 @@ use super::{
HandshakeRole, MidHandshake, ProcessingResult,
};
use crate::{
error::{Error, Result},
error::{Error, UrlErrorType, Result},
protocol::{Role, WebSocket, WebSocketConfig},
};
@ -98,7 +98,7 @@ fn generate_request(request: Request, key: &str) -> Result<Vec<u8>> {
let uri = request.uri();
let authority =
uri.authority().ok_or_else(|| Error::Url("No host name in the URL".into()))?.as_str();
uri.authority().ok_or_else(|| Error::Url(UrlErrorType::NoHostName))?.as_str();
let host = if let Some(idx) = authority.find('@') {
// handle possible name:password@
authority.split_at(idx + 1).1
@ -106,7 +106,7 @@ fn generate_request(request: Request, key: &str) -> Result<Vec<u8>> {
authority
};
if authority.is_empty() {
return Err(Error::Url("URL contains empty host name".into()));
return Err(Error::Url(UrlErrorType::EmptyHostName));
}
write!(
@ -121,7 +121,7 @@ fn generate_request(request: Request, key: &str) -> Result<Vec<u8>> {
version = request.version(),
host = host,
path =
uri.path_and_query().ok_or_else(|| Error::Url("No path/query in URL".into()))?.as_str(),
uri.path_and_query().ok_or_else(|| Error::Url(UrlErrorType::NoPathOrQuery))?.as_str(),
key = key
)
.unwrap();

Loading…
Cancel
Save