Replace derive_more with thiserror

This commit is contained in:
Nikolay Kim 2022-01-26 23:12:37 +06:00
parent cd0b6b75ba
commit 321218f80b
20 changed files with 234 additions and 272 deletions

View file

@ -20,7 +20,6 @@ ntex-bytes = "0.1.8"
ntex-io = "0.1.0"
ntex-util = "0.1.6"
async-oneshot = "0.5.0"
derive_more = "0.99"
log = "0.4"
pin-project-lite = "0.2"
async-std = { version = "1", features = ["unstable"] }

View file

@ -22,7 +22,6 @@ ntex-util = "0.1.9"
async-oneshot = "0.5.0"
futures-lite = "1.12"
futures-channel = "0.3"
derive_more = "0.99"
log = "0.4"
pin-project-lite = "0.2"

View file

@ -30,7 +30,6 @@ async-std = ["async_std/unstable"]
[dependencies]
async-oneshot = "0.5.0"
async-channel = "1.6.1"
derive_more = "0.99.14"
futures-core = "0.3"
log = "0.4"
pin-project-lite = "0.2"

View file

@ -189,7 +189,7 @@ mod tokio {
#[cfg(feature = "async-std")]
mod asyncstd {
use futures_core::ready;
use std::{future::Future, pin::Pin, task::Context, task::Poll};
use std::{fmt, future::Future, pin::Pin, task::Context, task::Poll};
/// Runs the provided future, blocking the current thread until the future
/// completes.
@ -245,8 +245,15 @@ mod asyncstd {
}
}
#[derive(Debug, Copy, Clone, derive_more::Display)]
#[derive(Debug, Copy, Clone)]
pub struct JoinError;
impl fmt::Display for JoinError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "JoinError")
}
}
impl std::error::Error for JoinError {}
pub struct JoinHandle<T> {

View file

@ -1,5 +1,9 @@
# Changes
## [0.5.12] - 2022-01-xx
* Replace derive_more with thiserror
## [0.5.11] - 2022-01-23
* web: Refactor ws support

View file

@ -1,6 +1,6 @@
[package]
name = "ntex"
version = "0.5.11"
version = "0.5.12"
authors = ["ntex contributors <team@ntex.rs>"]
description = "Framework for composable network services"
readme = "README.md"
@ -61,9 +61,10 @@ ntex-tokio = "0.1.2"
ntex-glommio = { version = "0.1.0", optional = true }
ntex-async-std = { version = "0.1.0", optional = true }
async-oneshot = "0.5.0"
async-channel = "1.6.1"
base64 = "0.13"
bitflags = "1.3"
derive_more = "0.99"
log = "0.4"
num_cpus = "1.13"
nanorand = { version = "0.6.1", default-features = false, features = ["std", "wyrand"] }
@ -74,9 +75,7 @@ sha-1 = "0.10"
slab = "0.4"
serde = { version = "1.0", features=["derive"] }
socket2 = "0.4"
async-oneshot = "0.5.0"
async-channel = "1.6.1"
thiserror = "1.0"
# http/web framework
h2 = "0.3.9"

View file

@ -1,28 +1,26 @@
use std::io;
use derive_more::{Display, From};
#[derive(Debug, From, Display)]
#[derive(thiserror::Error, Debug)]
pub enum ConnectError {
/// Failed to resolve the hostname
#[from(ignore)]
#[display(fmt = "Failed resolving hostname: {}", _0)]
#[error("Failed resolving hostname: {0}")]
Resolver(io::Error),
/// No dns records
#[display(fmt = "No dns records found for the input")]
#[error("No dns records found for the input")]
NoRecords,
/// Invalid input
#[error("Invalid input")]
InvalidInput,
/// Unresolved host name
#[display(fmt = "Connector received `Connect` method with unresolved host")]
#[error("Connector received `Connect` method with unresolved host")]
Unresolved,
/// Connection io error
#[display(fmt = "{}", _0)]
Io(io::Error),
#[error("{0}")]
Io(#[from] io::Error),
}
impl Clone for ConnectError {

View file

@ -1,8 +1,8 @@
//! Http client errors
use std::{error::Error, io};
use derive_more::{Display, From};
use serde_json::error::Error as JsonError;
use thiserror::Error;
#[cfg(feature = "openssl")]
use crate::connect::openssl::{HandshakeError, SslError};
@ -11,66 +11,61 @@ use crate::http::error::{HttpError, ParseError, PayloadError};
use crate::util::Either;
/// A set of errors that can occur during parsing json payloads
#[derive(Debug, Display, From)]
#[derive(Error, Debug)]
pub enum JsonPayloadError {
/// Content type error
#[display(fmt = "Content type error")]
#[error("Content type error")]
ContentType,
/// Deserialize error
#[display(fmt = "Json deserialize error: {}", _0)]
Deserialize(JsonError),
#[error("Json deserialize error: {0}")]
Deserialize(#[from] JsonError),
/// Payload error
#[display(fmt = "Error that occur during reading payload: {}", _0)]
Payload(PayloadError),
#[error("Error that occur during reading payload: {0}")]
Payload(#[from] PayloadError),
}
impl std::error::Error for JsonPayloadError {}
/// A set of errors that can occur while connecting to an HTTP host
#[derive(Debug, Display, From)]
#[derive(Error, Debug)]
pub enum ConnectError {
/// SSL feature is not enabled
#[display(fmt = "SSL is not supported")]
#[error("SSL is not supported")]
SslIsNotSupported,
/// SSL error
#[cfg(feature = "openssl")]
#[display(fmt = "{}", _0)]
SslError(SslError),
#[error("{0}")]
SslError(#[from] SslError),
/// SSL Handshake error
#[cfg(feature = "openssl")]
#[display(fmt = "{}", _0)]
#[error("{0}")]
SslHandshakeError(String),
/// Failed to resolve the hostname
#[from(ignore)]
#[display(fmt = "Failed resolving hostname: {}", _0)]
Resolver(io::Error),
#[error("Failed resolving hostname: {0}")]
Resolver(#[from] io::Error),
/// No dns records
#[display(fmt = "No dns records found for the input")]
#[error("No dns records found for the input")]
NoRecords,
/// Http2 error
#[display(fmt = "{}", _0)]
H2(h2::Error),
#[error("{0}")]
H2(#[from] h2::Error),
/// Connecting took too long
#[display(fmt = "Timeout out while establishing connection")]
#[error("Timeout out while establishing connection")]
Timeout,
/// Connector has been disconnected
#[display(fmt = "Connector has been disconnected")]
#[error("Connector has been disconnected")]
Disconnected(Option<io::Error>),
/// Unresolved host name
#[display(fmt = "Connector received `Connect` method with unresolved host")]
#[error("Connector received `Connect` method with unresolved host")]
Unresolved,
}
impl std::error::Error for ConnectError {}
impl From<crate::connect::ConnectError> for ConnectError {
fn from(err: crate::connect::ConnectError) -> ConnectError {
match err {
@ -90,51 +85,50 @@ impl<T: std::fmt::Debug> From<HandshakeError<T>> for ConnectError {
}
}
#[derive(Debug, Display, From)]
#[derive(Error, Debug)]
pub enum InvalidUrl {
#[display(fmt = "Missing url scheme")]
#[error("Missing url scheme")]
MissingScheme,
#[display(fmt = "Unknown url scheme")]
#[error("Unknown url scheme")]
UnknownScheme,
#[display(fmt = "Missing host name")]
#[error("Missing host name")]
MissingHost,
#[display(fmt = "Url parse error: {}", _0)]
Http(HttpError),
#[error("Url parse error: {0}")]
Http(#[from] HttpError),
}
impl std::error::Error for InvalidUrl {}
/// A set of errors that can occur during request sending and response reading
#[derive(Debug, Display, From)]
#[derive(Error, Debug)]
pub enum SendRequestError {
/// Invalid URL
#[display(fmt = "Invalid URL: {}", _0)]
Url(InvalidUrl),
#[error("Invalid URL: {0}")]
Url(#[from] InvalidUrl),
/// Failed to connect to host
#[display(fmt = "Failed to connect to host: {}", _0)]
Connect(ConnectError),
#[error("Failed to connect to host: {0}")]
Connect(#[from] ConnectError),
/// Error sending request
Send(io::Error),
#[error("Error sending request: {0}")]
Send(#[from] io::Error),
/// Error parsing response
Response(ParseError),
#[error("Error during response parsing: {0}")]
Response(#[from] ParseError),
/// Http error
#[display(fmt = "{}", _0)]
Http(HttpError),
#[error("{0}")]
Http(#[from] HttpError),
/// Http2 error
#[display(fmt = "{}", _0)]
H2(h2::Error),
#[error("Http2 error {0}")]
H2(#[from] h2::Error),
/// Response took too long
#[display(fmt = "Timeout out while waiting for response")]
#[error("Timeout out while waiting for response")]
Timeout,
/// Tunnels are not supported for http2 connection
#[display(fmt = "Tunnels are not supported for http2 connection")]
#[error("Tunnels are not supported for http2 connection")]
TunnelNotSupported,
/// Error sending request body
Error(Box<dyn Error>),
#[error("Error sending request body {0}")]
Error(#[from] 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 {
@ -154,18 +148,16 @@ impl From<Either<ParseError, io::Error>> for SendRequestError {
}
/// A set of errors that can occur during freezing a request
#[derive(Debug, Display, From)]
#[derive(Error, Debug)]
pub enum FreezeRequestError {
/// Invalid URL
#[display(fmt = "Invalid URL: {}", _0)]
Url(InvalidUrl),
#[error("Invalid URL: {0}")]
Url(#[from] InvalidUrl),
/// Http error
#[display(fmt = "{}", _0)]
Http(HttpError),
#[error("{0}")]
Http(#[from] HttpError),
}
impl std::error::Error for FreezeRequestError {}
impl From<FreezeRequestError> for SendRequestError {
fn from(e: FreezeRequestError) -> Self {
match e {

View file

@ -19,10 +19,12 @@ use super::error::{FreezeRequestError, InvalidUrl, SendRequestError};
use super::response::ClientResponse;
use super::ClientConfig;
#[derive(Debug, From)]
#[derive(thiserror::Error, Debug)]
pub(crate) enum PrepForSendingError {
Url(InvalidUrl),
Http(HttpError),
#[error("Invalid url {0}")]
Url(#[from] InvalidUrl),
#[error("Invalid http request {0}")]
Http(#[from] HttpError),
}
impl From<PrepForSendingError> for FreezeRequestError {

View file

@ -57,42 +57,41 @@ impl ResponseError for io::Error {}
impl ResponseError for serde_json::error::Error {}
/// A set of errors that can occur during parsing HTTP streams
#[derive(Debug, Display, From)]
#[derive(thiserror::Error, Debug)]
pub enum ParseError {
/// An invalid `Method`, such as `GE.T`.
#[display(fmt = "Invalid Method specified")]
#[error("Invalid Method specified")]
Method,
/// An invalid `Uri`, such as `exam ple.domain`.
#[display(fmt = "Uri error: {}", _0)]
Uri(InvalidUri),
#[error("Uri error: {0}")]
Uri(#[from] InvalidUri),
/// An invalid `HttpVersion`, such as `HTP/1.1`
#[display(fmt = "Invalid HTTP version specified")]
#[error("Invalid HTTP version specified")]
Version,
/// An invalid `Header`.
#[display(fmt = "Invalid Header provided")]
#[error("Invalid Header provided")]
Header,
/// A message head is too large to be reasonable.
#[display(fmt = "Message head is too large")]
#[error("Message head is too large")]
TooLarge,
/// A message reached EOF, but is not complete.
#[display(fmt = "Message is incomplete")]
#[error("Message is incomplete")]
Incomplete,
/// An invalid `Status`, such as `1337 ELITE`.
#[display(fmt = "Invalid Status provided")]
#[error("Invalid Status provided")]
Status,
/// A timeout occurred waiting for an IO event.
#[allow(dead_code)]
#[display(fmt = "Timeout during parse")]
#[error("Timeout during parse")]
Timeout,
/// An `InvalidInput` occurred while trying to parse incoming stream.
#[error("`InvalidInput` occurred while trying to parse incoming stream: {0}")]
InvalidInput(&'static str),
/// Parsing a field as string failed
#[display(fmt = "UTF8 error: {}", _0)]
Utf8(Utf8Error),
#[error("UTF8 error: {0}")]
Utf8(#[from] Utf8Error),
}
impl std::error::Error for ParseError {}
impl From<FromUtf8Error> for ParseError {
fn from(err: FromUtf8Error) -> ParseError {
ParseError::Utf8(err.utf8_error())
@ -113,36 +112,32 @@ impl From<httparse::Error> for ParseError {
}
}
#[derive(Display, Debug, From)]
#[derive(thiserror::Error, Debug)]
/// A set of errors that can occur during payload parsing
pub enum PayloadError {
/// A payload reached EOF, but is not complete.
#[display(
fmt = "A payload reached EOF, but is not complete. With error: {:?}",
_0
)]
#[error("A payload reached EOF, but is not complete. With error: {0:?}")]
Incomplete(Option<io::Error>),
/// Content encoding stream corruption
#[display(fmt = "Cannot decode content-encoding.")]
#[error("Cannot decode content-encoding.")]
EncodingCorrupted,
/// A payload reached size limit.
#[display(fmt = "A payload reached size limit.")]
#[error("A payload reached size limit.")]
Overflow,
/// A payload length is unknown.
#[display(fmt = "A payload length is unknown.")]
#[error("A payload length is unknown.")]
UnknownLength,
/// Http2 payload error
#[display(fmt = "{}", _0)]
Http2Payload(h2::Error),
#[error("{0}")]
Http2Payload(#[from] h2::Error),
/// Parse error
Parse(ParseError),
#[error("Parse error: {0}")]
Parse(#[from] ParseError),
/// Io error
#[display(fmt = "{}", _0)]
Io(io::Error),
#[error("{0}")]
Io(#[from] io::Error),
}
impl std::error::Error for PayloadError {}
impl From<Either<PayloadError, io::Error>> for PayloadError {
fn from(err: Either<PayloadError, io::Error>) -> Self {
match err {
@ -152,64 +147,62 @@ impl From<Either<PayloadError, io::Error>> for PayloadError {
}
}
#[derive(Debug, Display, From)]
#[derive(thiserror::Error, Debug)]
/// A set of errors that can occur during dispatching http requests
pub enum DispatchError {
/// Service error
#[error("Service error")]
Service(Box<dyn ResponseError>),
#[from(ignore)]
/// Upgrade service error
#[error("Upgrade service error: {0}")]
Upgrade(Box<dyn std::error::Error>),
/// Peer is disconnected, error indicates that peer is disconnected because of it
#[display(fmt = "Disconnected: {:?}", _0)]
#[error("Disconnected: {0:?}")]
PeerGone(Option<io::Error>),
/// Http request parse error.
#[display(fmt = "Parse error: {}", _0)]
Parse(ParseError),
#[error("Parse error: {0}")]
Parse(#[from] ParseError),
/// Http response encoding error.
#[display(fmt = "Encode error: {}", _0)]
#[from(ignore)]
#[error("Encode error: {0}")]
Encode(io::Error),
/// Http/2 error
#[display(fmt = "{}", _0)]
H2(h2::Error),
#[error("{0}")]
H2(#[from] h2::Error),
/// The first request did not complete within the specified timeout.
#[display(fmt = "The first request did not complete within the specified timeout")]
#[error("The first request did not complete within the specified timeout")]
SlowRequestTimeout,
/// Disconnect timeout. Makes sense for ssl streams.
#[display(fmt = "Connection shutdown timeout")]
#[error("Connection shutdown timeout")]
DisconnectTimeout,
/// Payload is not consumed
#[display(fmt = "Task is completed but request's payload is not consumed")]
#[error("Task is completed but request's payload is not consumed")]
PayloadIsNotConsumed,
/// Malformed request
#[display(fmt = "Malformed request")]
#[error("Malformed request")]
MalformedRequest,
/// Response body processing error
#[display(fmt = "Response body processing error: {}", _0)]
#[error("Response body processing error: {0}")]
ResponsePayload(Box<dyn std::error::Error>),
/// Internal error
#[display(fmt = "Internal error")]
#[error("Internal error")]
InternalError,
/// Unknown error
#[display(fmt = "Unknown error")]
#[error("Unknown error")]
Unknown,
}
impl std::error::Error for DispatchError {}
impl From<io::Error> for DispatchError {
fn from(err: io::Error) -> Self {
DispatchError::PeerGone(Some(err))
@ -217,35 +210,31 @@ impl From<io::Error> for DispatchError {
}
/// A set of error that can occure during parsing content type
#[derive(PartialEq, Debug, Display)]
#[derive(thiserror::Error, PartialEq, Debug)]
pub enum ContentTypeError {
/// Cannot parse content type
#[display(fmt = "Cannot parse content type")]
#[error("Cannot parse content type")]
ParseError,
/// Unknown content encoding
#[display(fmt = "Unknown content encoding")]
#[error("Unknown content encoding")]
UnknownEncoding,
/// Unexpected Content-Type
#[display(fmt = "Unexpected Content-Type")]
#[error("Unexpected Content-Type")]
Unexpected,
/// Content-Type is expected
#[display(fmt = "Content-Type is expected")]
#[error("Content-Type is expected")]
Expected,
}
impl std::error::Error for ContentTypeError {}
/// Blocking operation execution error
#[derive(Debug, Display)]
#[derive(thiserror::Error, Debug)]
pub enum BlockingError<E: fmt::Debug> {
#[display(fmt = "{:?}", _0)]
#[error("{0:?}")]
Error(E),
#[display(fmt = "Thread pool is gone")]
#[error("Thread pool is gone")]
Canceled,
}
impl<E: fmt::Debug> std::error::Error for BlockingError<E> {}
impl From<crate::rt::JoinError> for PayloadError {
fn from(_: crate::rt::JoinError) -> Self {
PayloadError::Io(io::Error::new(

View file

@ -44,19 +44,21 @@ pin_project_lite::pin_project! {
}
}
#[derive(derive_more::Display)]
#[derive(thiserror::Error)]
enum State<B> {
#[error("State::Call")]
Call,
#[error("State::ReadRequest")]
ReadRequest,
#[error("State::ReadPayload")]
ReadPayload,
#[display(fmt = "State::SendPayload")]
SendPayload {
body: ResponseBody<B>,
},
#[display(fmt = "State::Upgrade")]
#[error("State::SendPayload")]
SendPayload { body: ResponseBody<B> },
#[error("State::Upgrade")]
Upgrade(Option<Request>),
#[display(fmt = "State::StopIo")]
#[error("State::StopIo")]
StopIo(Box<(IoBoxed, Codec)>),
#[error("State::Stop")]
Stop,
}

View file

@ -23,8 +23,6 @@
#[macro_use]
extern crate log;
#[macro_use]
extern crate derive_more;
#[cfg(not(test))] // Work around for rust-lang/rust#62127
pub use ntex_macros::{rt_main as main, rt_test as test};

View file

@ -1,7 +1,7 @@
//! Web error
use std::{cell::RefCell, fmt, io::Write, marker::PhantomData};
use derive_more::{Display, From};
use thiserror::Error;
pub use http::Error as HttpError;
pub use serde_json::error::Error as JsonError;
@ -78,114 +78,98 @@ where
}
/// Errors which can occur when attempting to work with `Data` extractor
#[derive(Debug, PartialEq, Display)]
#[derive(Error, Debug, PartialEq)]
pub enum DataExtractorError {
#[display(fmt = "App data is not configured, to configure use App::data()")]
#[error("App data is not configured, to configure use App::data()")]
NotConfigured,
}
impl std::error::Error for DataExtractorError {}
/// Errors which can occur when attempting to generate resource uri.
#[derive(Debug, PartialEq, Display, From)]
#[derive(Error, Debug, PartialEq)]
pub enum UrlGenerationError {
/// Resource not found
#[display(fmt = "Resource not found")]
#[error("Resource not found")]
ResourceNotFound,
/// Not all path pattern covered
#[display(fmt = "Not all path pattern covered")]
#[error("Not all path pattern covered")]
NotEnoughElements,
/// URL parse error
#[cfg(feature = "url")]
#[display(fmt = "{}", _0)]
ParseError(UrlParseError),
#[error("{0}")]
ParseError(#[from] UrlParseError),
}
impl std::error::Error for UrlGenerationError {}
/// A set of errors that can occur during parsing urlencoded payloads
#[derive(Debug, Display, From)]
#[derive(Error, Debug)]
pub enum UrlencodedError {
/// Cannot decode chunked transfer encoding
#[display(fmt = "Cannot decode chunked transfer encoding")]
#[error("Cannot decode chunked transfer encoding")]
Chunked,
/// Payload size is bigger than allowed. (default: 256kB)
#[display(
fmt = "Urlencoded payload size is bigger ({} bytes) than allowed (default: {} bytes)",
size,
limit
#[error(
"Urlencoded payload size is bigger ({size} bytes) than allowed (default: {limit} bytes)",
)]
Overflow { size: usize, limit: usize },
/// Payload size is unknown
#[display(fmt = "Payload size is unknown")]
#[error("Payload size is unknown")]
UnknownLength,
/// Content type error
#[display(fmt = "Content type error")]
#[error("Content type error")]
ContentType,
/// Parse error
#[display(fmt = "Parse error")]
#[error("Parse error")]
Parse,
/// Payload error
#[display(fmt = "Error that occur during reading payload: {}", _0)]
Payload(error::PayloadError),
#[error("Error that occur during reading payload: {0}")]
Payload(#[from] error::PayloadError),
}
impl std::error::Error for UrlencodedError {}
/// A set of errors that can occur during parsing json payloads
#[derive(Debug, Display, From)]
#[derive(Error, Debug)]
pub enum JsonPayloadError {
/// Payload size is bigger than allowed. (default: 32kB)
#[display(fmt = "Json payload size is bigger than allowed")]
#[error("Json payload size is bigger than allowed")]
Overflow,
/// Content type error
#[display(fmt = "Content type error")]
#[error("Content type error")]
ContentType,
/// Deserialize error
#[display(fmt = "Json deserialize error: {}", _0)]
Deserialize(serde_json::error::Error),
#[error("Json deserialize error: {0}")]
Deserialize(#[from] serde_json::error::Error),
/// Payload error
#[display(fmt = "Error that occur during reading payload: {}", _0)]
Payload(error::PayloadError),
#[error("Error that occur during reading payload: {0}")]
Payload(#[from] error::PayloadError),
}
impl std::error::Error for JsonPayloadError {}
/// A set of errors that can occur during parsing request paths
#[derive(Debug, Display, From)]
#[derive(Error, Debug)]
pub enum PathError {
/// Deserialize error
#[display(fmt = "Path deserialize error: {}", _0)]
Deserialize(serde::de::value::Error),
#[error("Path deserialize error: {0}")]
Deserialize(#[from] serde::de::value::Error),
}
impl std::error::Error for PathError {}
/// A set of errors that can occur during parsing query strings
#[derive(Debug, Display, From)]
#[derive(Error, Debug)]
pub enum QueryPayloadError {
/// Deserialize error
#[display(fmt = "Query deserialize error: {}", _0)]
Deserialize(serde::de::value::Error),
#[error("Query deserialize error: {0}")]
Deserialize(#[from] serde::de::value::Error),
}
impl std::error::Error for QueryPayloadError {}
#[derive(Debug, Display, From)]
#[derive(Error, Debug)]
pub enum PayloadError {
/// Http error.
#[display(fmt = "{:?}", _0)]
Http(error::HttpError),
#[display(fmt = "{}", _0)]
Payload(error::PayloadError),
#[display(fmt = "{}", _0)]
ContentType(error::ContentTypeError),
#[display(fmt = "Cannot decode body")]
#[error("{0:?}")]
Http(#[from] error::HttpError),
#[error("{0}")]
Payload(#[from] error::PayloadError),
#[error("{0}")]
ContentType(#[from] error::ContentTypeError),
#[error("Cannot decode body")]
Decoding,
}
impl std::error::Error for PayloadError {}
/// Helper type that can wrap any error and generate custom response.
///
/// In following example any `io::Error` will be converted into "BAD REQUEST"

View file

@ -23,6 +23,7 @@ impl ErrorRenderer for DefaultError {
}
/// Generic error container for errors that supports `DefaultError` renderer.
#[derive(thiserror::Error)]
pub struct Error {
cause: Box<dyn WebResponseError<DefaultError>>,
}
@ -49,8 +50,6 @@ impl<T: WebResponseError<DefaultError>> From<T> for Error {
}
}
impl std::error::Error for Error {}
impl ErrorContainer for Error {
fn error_response(&self, req: &HttpRequest) -> HttpResponse {
self.cause.error_response(req)

View file

@ -344,8 +344,8 @@ mod tests {
use crate::util::Bytes;
use crate::web::test::{from_request, respond_to, TestRequest};
#[derive(Deserialize, Serialize, Debug, PartialEq, derive_more::Display)]
#[display(fmt = "{}", "hello")]
#[derive(Deserialize, Serialize, Debug, PartialEq, thiserror::Error)]
#[error("Info({hello})")]
struct Info {
hello: String,
counter: i64,

View file

@ -376,9 +376,8 @@ mod tests {
use crate::util::Bytes;
use crate::web::test::{from_request, respond_to, TestRequest};
#[derive(
serde::Serialize, serde::Deserialize, PartialEq, Debug, derive_more::Display,
)]
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug, thiserror::Error)]
#[error("MyObject({name})")]
struct MyObject {
name: String,
}

View file

@ -175,14 +175,12 @@ where
#[cfg(test)]
mod tests {
use derive_more::Display;
use super::*;
use crate::router::Router;
use crate::web::test::{from_request, TestRequest};
#[derive(serde::Deserialize, Debug, Display)]
#[display(fmt = "MyStruct({}, {})", key, value)]
#[derive(thiserror::Error, serde::Deserialize, Debug)]
#[error("MyStruct({key}, {value})")]
struct MyStruct {
key: String,
value: String,

View file

@ -149,12 +149,11 @@ where
#[cfg(test)]
mod tests {
use derive_more::Display;
use super::*;
use crate::web::test::{from_request, TestRequest};
#[derive(serde::Deserialize, Debug, Display)]
#[derive(serde::Deserialize, Debug, thiserror::Error)]
#[error("Id({id})")]
struct Id {
id: String,
}
@ -168,7 +167,7 @@ mod tests {
let mut s = Query::<Id>::from_query(req.query_string()).unwrap();
assert_eq!(s.id, "test");
assert_eq!(format!("{}, {:?}", s, s), "test, Id { id: \"test\" }");
assert_eq!(format!("{}, {:?}", s, s), "Id(test), Id { id: \"test\" }");
s.id = "test1".to_string();
let s = s.into_inner();
@ -187,7 +186,7 @@ mod tests {
let mut s = from_request::<Query<Id>>(&req, &mut pl).await.unwrap();
assert_eq!(s.id, "test");
assert_eq!(format!("{}, {:?}", s, s), "test, Id { id: \"test\" }");
assert_eq!(format!("{}, {:?}", s, s), "Id(test), Id { id: \"test\" }");
s.id = "test1".to_string();
let s = s.into_inner();

View file

@ -1,117 +1,113 @@
//! WebSocket protocol related errors.
use std::{error, io};
use std::io;
use derive_more::{Display, From};
use thiserror::Error;
use crate::connect::ConnectError;
use crate::http::error::{HttpError, ParseError, ResponseError};
use crate::http::{header::HeaderValue, header::ALLOW, Response, StatusCode};
use crate::util::Either;
use crate::{connect::ConnectError, util::Either};
use super::OpCode;
/// Websocket service errors
#[derive(Debug, Display)]
#[derive(Error, Debug)]
pub enum WsError<E> {
#[error("Service error")]
Service(E),
/// Keep-alive error
#[error("Keep-alive error")]
KeepAlive,
/// Ws protocol level error
#[error("Ws protocol level error")]
Protocol(ProtocolError),
/// Peer has been disconnected
#[display(fmt = "Peer has been disconnected: {:?}", _0)]
#[error("Peer has been disconnected: {0:?}")]
Disconnected(Option<io::Error>),
}
/// Websocket protocol errors
#[derive(Debug, Display, From)]
#[derive(Error, Debug)]
pub enum ProtocolError {
/// Received an unmasked frame from client
#[display(fmt = "Received an unmasked frame from client")]
#[error("Received an unmasked frame from client")]
UnmaskedFrame,
/// Received a masked frame from server
#[display(fmt = "Received a masked frame from server")]
#[error("Received a masked frame from server")]
MaskedFrame,
/// Encountered invalid opcode
#[display(fmt = "Invalid opcode: {}", _0)]
#[error("Invalid opcode: {0}")]
InvalidOpcode(u8),
/// Invalid control frame length
#[display(fmt = "Invalid control frame length: {}", _0)]
#[error("Invalid control frame length: {0}")]
InvalidLength(usize),
/// Bad web socket op code
#[display(fmt = "Bad web socket op code")]
#[error("Bad web socket op code")]
BadOpCode,
/// A payload reached size limit.
#[display(fmt = "A payload reached size limit.")]
#[error("A payload reached size limit.")]
Overflow,
/// Continuation is not started
#[display(fmt = "Continuation is not started.")]
#[error("Continuation is not started.")]
ContinuationNotStarted,
/// Received new continuation but it is already started
#[display(fmt = "Received new continuation but it is already started")]
#[error("Received new continuation but it is already started")]
ContinuationStarted,
/// Unknown continuation fragment
#[display(fmt = "Unknown continuation fragment.")]
#[error("Unknown continuation fragment {0}")]
ContinuationFragment(OpCode),
}
impl std::error::Error for ProtocolError {}
/// Websocket client error
#[derive(Debug, Display, From)]
#[derive(Error, Debug)]
pub enum WsClientBuilderError {
#[display(fmt = "Missing url scheme")]
#[error("Missing url scheme")]
MissingScheme,
#[display(fmt = "Unknown url scheme")]
#[error("Unknown url scheme")]
UnknownScheme,
#[display(fmt = "Missing host name")]
#[error("Missing host name")]
MissingHost,
#[display(fmt = "Url parse error: {}", _0)]
Http(HttpError),
#[error("Url parse error: {0}")]
Http(#[from] HttpError),
}
impl std::error::Error for WsClientBuilderError {}
/// Websocket client error
#[derive(Debug, Display, From)]
#[derive(Error, Debug)]
pub enum WsClientError {
/// Invalid response
#[display(fmt = "Invalid response")]
InvalidResponse(ParseError),
#[error("Invalid response")]
InvalidResponse(#[from] ParseError),
/// Invalid response status
#[display(fmt = "Invalid response status")]
#[error("Invalid response status")]
InvalidResponseStatus(StatusCode),
/// Invalid upgrade header
#[display(fmt = "Invalid upgrade header")]
#[error("Invalid upgrade header")]
InvalidUpgradeHeader,
/// Invalid connection header
#[display(fmt = "Invalid connection header")]
#[error("Invalid connection header")]
InvalidConnectionHeader(HeaderValue),
/// Missing CONNECTION header
#[display(fmt = "Missing CONNECTION header")]
#[error("Missing CONNECTION header")]
MissingConnectionHeader,
/// Missing SEC-WEBSOCKET-ACCEPT header
#[display(fmt = "Missing SEC-WEBSOCKET-ACCEPT header")]
#[error("Missing SEC-WEBSOCKET-ACCEPT header")]
MissingWebSocketAcceptHeader,
/// Invalid challenge response
#[display(fmt = "Invalid challenge response")]
#[error("Invalid challenge response")]
InvalidChallengeResponse(String, HeaderValue),
/// Protocol error
#[display(fmt = "{}", _0)]
Protocol(ProtocolError),
#[error("{0}")]
Protocol(#[from] ProtocolError),
/// Response took too long
#[display(fmt = "Timeout out while waiting for response")]
#[error("Timeout out while waiting for response")]
Timeout,
/// Failed to connect to host
#[display(fmt = "Failed to connect to host: {}", _0)]
Connect(ConnectError),
#[error("Failed to connect to host: {0}")]
Connect(#[from] ConnectError),
/// Connector has been disconnected
#[display(fmt = "Connector has been disconnected: {:?}", _0)]
#[error("Connector has been disconnected: {0:?}")]
Disconnected(Option<io::Error>),
}
impl error::Error for WsClientError {}
impl From<Either<ParseError, io::Error>> for WsClientError {
fn from(err: Either<ParseError, io::Error>) -> Self {
match err {
@ -128,30 +124,28 @@ impl From<Either<io::Error, io::Error>> for WsClientError {
}
/// Websocket handshake errors
#[derive(PartialEq, Debug, Display)]
#[derive(Error, PartialEq, Debug)]
pub enum HandshakeError {
/// Only get method is allowed
#[display(fmt = "Method not allowed")]
#[error("Method not allowed")]
GetMethodRequired,
/// Upgrade header if not set to websocket
#[display(fmt = "Websocket upgrade is expected")]
#[error("Websocket upgrade is expected")]
NoWebsocketUpgrade,
/// Connection header is not set to upgrade
#[display(fmt = "Connection upgrade is expected")]
#[error("Connection upgrade is expected")]
NoConnectionUpgrade,
/// Websocket version header is not set
#[display(fmt = "Websocket version header is required")]
#[error("Websocket version header is required")]
NoVersionHeader,
/// Unsupported websocket version
#[display(fmt = "Unsupported version")]
#[error("Unsupported version")]
UnsupportedVersion,
/// Websocket key is not set or wrong
#[display(fmt = "Unknown websocket key")]
#[error("Unknown websocket key")]
BadWebsocketKey,
}
impl std::error::Error for HandshakeError {}
impl ResponseError for HandshakeError {
fn error_response(&self) -> Response {
match *self {

View file

@ -1,11 +1,11 @@
use std::{future::Future, io, io::Read, io::Write, pin::Pin, task::Context, task::Poll};
use brotli2::write::{BrotliDecoder, BrotliEncoder};
use derive_more::Display;
use flate2::read::GzDecoder;
use flate2::write::{GzEncoder, ZlibDecoder, ZlibEncoder};
use flate2::Compression;
use rand::{distributions::Alphanumeric, Rng};
use thiserror::Error;
use ntex::http::body::Body;
use ntex::http::header::{
@ -1092,11 +1092,12 @@ async fn test_slow_request() {
#[ntex::test]
async fn test_custom_error() {
#[derive(Debug, Display)]
#[derive(Error, Debug)]
#[error("TestError")]
struct TestError;
impl std::error::Error for TestError {}
#[derive(Debug, Display)]
#[derive(Error, Debug)]
#[error("JsonContainer({0})")]
struct JsonContainer(Box<dyn WebResponseError<JsonRenderer>>);
impl ntex::web::ErrorContainer for JsonContainer {