use std::{error::Error, io};
use derive_more::{Display, From};
use either::Either;
use serde_json::error::Error as JsonError;
#[cfg(feature = "openssl")]
use crate::connect::openssl::{HandshakeError, SslError};
use crate::connect::ResolveError;
use crate::http::error::{HttpError, ParseError, PayloadError};
use crate::http::header::HeaderValue;
use crate::http::StatusCode;
use crate::ws::ProtocolError;
#[derive(Debug, Display, From)]
pub enum WsClientError {
#[display(fmt = "Invalid response status")]
InvalidResponseStatus(StatusCode),
#[display(fmt = "Invalid upgrade header")]
InvalidUpgradeHeader,
#[display(fmt = "Invalid connection header")]
InvalidConnectionHeader(HeaderValue),
#[display(fmt = "Missing CONNECTION header")]
MissingConnectionHeader,
#[display(fmt = "Missing SEC-WEBSOCKET-ACCEPT header")]
MissingWebSocketAcceptHeader,
#[display(fmt = "Invalid challenge response")]
InvalidChallengeResponse(String, HeaderValue),
#[display(fmt = "{}", _0)]
Protocol(ProtocolError),
#[display(fmt = "{}", _0)]
SendRequest(SendRequestError),
}
impl std::error::Error for WsClientError {}
impl From<InvalidUrl> for WsClientError {
fn from(err: InvalidUrl) -> Self {
WsClientError::SendRequest(err.into())
}
}
impl From<HttpError> for WsClientError {
fn from(err: HttpError) -> Self {
WsClientError::SendRequest(err.into())
}
}
#[derive(Debug, Display, From)]
pub enum JsonPayloadError {
#[display(fmt = "Content type error")]
ContentType,
#[display(fmt = "Json deserialize error: {}", _0)]
Deserialize(JsonError),
#[display(fmt = "Error that occur during reading payload: {}", _0)]
Payload(PayloadError),
}
impl std::error::Error for JsonPayloadError {}
#[derive(Debug, Display, From)]
pub enum ConnectError {
#[display(fmt = "SSL is not supported")]
SslIsNotSupported,
#[cfg(feature = "openssl")]
#[display(fmt = "{}", _0)]
SslError(SslError),
#[cfg(feature = "openssl")]
#[display(fmt = "{}", _0)]
SslHandshakeError(String),
#[display(fmt = "Failed resolving hostname: {}", _0)]
Resolver(ResolveError),
#[display(fmt = "No dns records found for the input")]
NoRecords,
#[display(fmt = "{}", _0)]
H2(h2::Error),
#[display(fmt = "Timeout out while establishing connection")]
Timeout,
#[display(fmt = "Internal error: connector has been disconnected")]
Disconnected,
#[display(fmt = "Connector received `Connect` method with unresolved host")]
Unresolved,
#[display(fmt = "{}", _0)]
Io(io::Error),
}
impl std::error::Error for ConnectError {}
impl From<crate::connect::ConnectError> for ConnectError {
fn from(err: crate::connect::ConnectError) -> ConnectError {
match err {
crate::connect::ConnectError::Resolver(e) => ConnectError::Resolver(e),
crate::connect::ConnectError::NoRecords => ConnectError::NoRecords,
crate::connect::ConnectError::InvalidInput => panic!(),
crate::connect::ConnectError::Unresolved => ConnectError::Unresolved,
crate::connect::ConnectError::Io(e) => ConnectError::Io(e),
}
}
}
#[cfg(feature = "openssl")]
impl<T: std::fmt::Debug> From<HandshakeError<T>> for ConnectError {
fn from(err: HandshakeError<T>) -> ConnectError {
ConnectError::SslHandshakeError(format!("{:?}", err))
}
}
#[derive(Debug, Display, From)]
pub enum InvalidUrl {
#[display(fmt = "Missing url scheme")]
MissingScheme,
#[display(fmt = "Unknown url scheme")]
UnknownScheme,
#[display(fmt = "Missing host name")]
MissingHost,
#[display(fmt = "Url parse error: {}", _0)]
Http(HttpError),
}
impl std::error::Error for InvalidUrl {}
#[derive(Debug, Display, From)]
pub enum SendRequestError {
#[display(fmt = "Invalid URL: {}", _0)]
Url(InvalidUrl),
#[display(fmt = "Failed to connect to host: {}", _0)]
Connect(ConnectError),
Send(io::Error),
Response(ParseError),
#[display(fmt = "{}", _0)]
Http(HttpError),
#[display(fmt = "{}", _0)]
H2(h2::Error),
#[display(fmt = "Timeout out while waiting for response")]
Timeout,
#[display(fmt = "Tunnels are not supported for http2 connection")]
TunnelNotSupported,
Error(Box<dyn Error>),
}
impl std::error::Error for SendRequestError {}
impl From<Either<io::Error, io::Error>> for SendRequestError {
fn from(err: Either<io::Error, io::Error>) -> Self {
match err {
Either::Left(err) => SendRequestError::Send(err),
Either::Right(err) => SendRequestError::Send(err),
}
}
}
impl From<Either<ParseError, io::Error>> for SendRequestError {
fn from(err: Either<ParseError, io::Error>) -> Self {
match err {
Either::Left(err) => SendRequestError::Response(err),
Either::Right(err) => SendRequestError::Send(err),
}
}
}
#[derive(Debug, Display, From)]
pub enum FreezeRequestError {
#[display(fmt = "Invalid URL: {}", _0)]
Url(InvalidUrl),
#[display(fmt = "{}", _0)]
Http(HttpError),
}
impl std::error::Error for FreezeRequestError {}
impl From<FreezeRequestError> for SendRequestError {
fn from(e: FreezeRequestError) -> Self {
match e {
FreezeRequestError::Url(e) => e.into(),
FreezeRequestError::Http(e) => e.into(),
}
}
}