1use std::any::TypeId;
3use std::cell::RefCell;
4use std::io::Write;
5use std::str::Utf8Error;
6use std::string::FromUtf8Error;
7use std::{fmt, io, result};
8
9use requiem_codec::{Decoder, Encoder};
10pub use requiem_threadpool::BlockingError;
11use requiem_utils::framed::DispatcherError as FramedDispatcherError;
12use requiem_utils::timeout::TimeoutError;
13use bytes::BytesMut;
14use derive_more::{Display, From};
15pub use futures_channel::oneshot::Canceled;
16use http::uri::InvalidUri;
17use http::{header, Error as HttpError, StatusCode};
18use httparse;
19use serde::de::value::Error as DeError;
20use serde_json::error::Error as JsonError;
21use serde_urlencoded::ser::Error as FormError;
22
23use crate::body::Body;
25pub use crate::cookie::ParseError as CookieParseError;
26use crate::helpers::Writer;
27use crate::response::{Response, ResponseBuilder};
28
29pub type Result<T, E = Error> = result::Result<T, E>;
36
37pub struct Error {
48 cause: Box<dyn ResponseError>,
49}
50
51impl Error {
52 pub fn as_response_error(&self) -> &dyn ResponseError {
54 self.cause.as_ref()
55 }
56
57 pub fn as_error<T: ResponseError + 'static>(&self) -> Option<&T> {
59 ResponseError::downcast_ref(self.cause.as_ref())
60 }
61}
62
63pub trait ResponseError: fmt::Debug + fmt::Display {
65 fn status_code(&self) -> StatusCode {
69 StatusCode::INTERNAL_SERVER_ERROR
70 }
71
72 fn error_response(&self) -> Response {
76 let mut resp = Response::new(self.status_code());
77 let mut buf = BytesMut::new();
78 let _ = write!(Writer(&mut buf), "{}", self);
79 resp.headers_mut().insert(
80 header::CONTENT_TYPE,
81 header::HeaderValue::from_static("text/plain; charset=utf-8"),
82 );
83 resp.set_body(Body::from(buf))
84 }
85
86 #[doc(hidden)]
87 fn __private_get_type_id__(&self) -> TypeId
88 where
89 Self: 'static,
90 {
91 TypeId::of::<Self>()
92 }
93}
94
95impl dyn ResponseError + 'static {
96 pub fn downcast_ref<T: ResponseError + 'static>(&self) -> Option<&T> {
98 if self.__private_get_type_id__() == TypeId::of::<T>() {
99 unsafe { Some(&*(self as *const dyn ResponseError as *const T)) }
100 } else {
101 None
102 }
103 }
104}
105
106impl fmt::Display for Error {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 fmt::Display::fmt(&self.cause, f)
109 }
110}
111
112impl fmt::Debug for Error {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 write!(f, "{:?}", &self.cause)
115 }
116}
117
118impl std::error::Error for Error {
119 fn cause(&self) -> Option<&dyn std::error::Error> {
120 None
121 }
122
123 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
124 None
125 }
126}
127
128impl From<()> for Error {
129 fn from(_: ()) -> Self {
130 Error::from(UnitError)
131 }
132}
133
134impl From<std::convert::Infallible> for Error {
135 fn from(_: std::convert::Infallible) -> Self {
136 unreachable!()
139 }
140}
141
142impl From<Error> for Response {
144 fn from(err: Error) -> Self {
145 Response::from_error(err)
146 }
147}
148
149impl<T: ResponseError + 'static> From<T> for Error {
151 fn from(err: T) -> Error {
152 Error {
153 cause: Box::new(err),
154 }
155 }
156}
157
158impl From<Response> for Error {
160 fn from(res: Response) -> Error {
161 InternalError::from_response("", res).into()
162 }
163}
164
165impl From<ResponseBuilder> for Error {
167 fn from(mut res: ResponseBuilder) -> Error {
168 InternalError::from_response("", res.finish()).into()
169 }
170}
171
172impl<E: ResponseError> ResponseError for TimeoutError<E> {
174 fn status_code(&self) -> StatusCode {
175 match self {
176 TimeoutError::Service(e) => e.status_code(),
177 TimeoutError::Timeout => StatusCode::GATEWAY_TIMEOUT,
178 }
179 }
180}
181
182#[derive(Debug, Display)]
183#[display(fmt = "UnknownError")]
184struct UnitError;
185
186impl ResponseError for UnitError {}
188
189impl ResponseError for JsonError {}
191
192impl ResponseError for FormError {}
194
195#[cfg(feature = "openssl")]
196impl ResponseError for requiem_connect::ssl::openssl::SslError {}
198
199#[cfg(feature = "openssl")]
200impl<T: std::fmt::Debug> ResponseError for requiem_tls::openssl::HandshakeError<T> {}
202
203impl ResponseError for DeError {
205 fn status_code(&self) -> StatusCode {
206 StatusCode::BAD_REQUEST
207 }
208}
209
210impl ResponseError for Canceled {}
212
213impl<E: fmt::Debug> ResponseError for BlockingError<E> {}
215
216impl ResponseError for Utf8Error {
218 fn status_code(&self) -> StatusCode {
219 StatusCode::BAD_REQUEST
220 }
221}
222
223impl ResponseError for HttpError {}
226
227impl ResponseError for io::Error {
229 fn status_code(&self) -> StatusCode {
230 match self.kind() {
231 io::ErrorKind::NotFound => StatusCode::NOT_FOUND,
232 io::ErrorKind::PermissionDenied => StatusCode::FORBIDDEN,
233 _ => StatusCode::INTERNAL_SERVER_ERROR,
234 }
235 }
236}
237
238impl ResponseError for header::InvalidHeaderValue {
240 fn status_code(&self) -> StatusCode {
241 StatusCode::BAD_REQUEST
242 }
243}
244
245#[derive(Debug, Display)]
247pub enum ParseError {
248 #[display(fmt = "Invalid Method specified")]
250 Method,
251 #[display(fmt = "Uri error: {}", _0)]
253 Uri(InvalidUri),
254 #[display(fmt = "Invalid HTTP version specified")]
256 Version,
257 #[display(fmt = "Invalid Header provided")]
259 Header,
260 #[display(fmt = "Message head is too large")]
262 TooLarge,
263 #[display(fmt = "Message is incomplete")]
265 Incomplete,
266 #[display(fmt = "Invalid Status provided")]
268 Status,
269 #[allow(dead_code)]
271 #[display(fmt = "Timeout")]
272 Timeout,
273 #[display(fmt = "IO error: {}", _0)]
276 Io(io::Error),
277 #[display(fmt = "UTF8 error: {}", _0)]
279 Utf8(Utf8Error),
280}
281
282impl ResponseError for ParseError {
284 fn status_code(&self) -> StatusCode {
285 StatusCode::BAD_REQUEST
286 }
287}
288
289impl From<io::Error> for ParseError {
290 fn from(err: io::Error) -> ParseError {
291 ParseError::Io(err)
292 }
293}
294
295impl From<InvalidUri> for ParseError {
296 fn from(err: InvalidUri) -> ParseError {
297 ParseError::Uri(err)
298 }
299}
300
301impl From<Utf8Error> for ParseError {
302 fn from(err: Utf8Error) -> ParseError {
303 ParseError::Utf8(err)
304 }
305}
306
307impl From<FromUtf8Error> for ParseError {
308 fn from(err: FromUtf8Error) -> ParseError {
309 ParseError::Utf8(err.utf8_error())
310 }
311}
312
313impl From<httparse::Error> for ParseError {
314 fn from(err: httparse::Error) -> ParseError {
315 match err {
316 httparse::Error::HeaderName
317 | httparse::Error::HeaderValue
318 | httparse::Error::NewLine
319 | httparse::Error::Token => ParseError::Header,
320 httparse::Error::Status => ParseError::Status,
321 httparse::Error::TooManyHeaders => ParseError::TooLarge,
322 httparse::Error::Version => ParseError::Version,
323 }
324 }
325}
326
327#[derive(Display, Debug)]
328pub enum PayloadError {
330 #[display(
332 fmt = "A payload reached EOF, but is not complete. With error: {:?}",
333 _0
334 )]
335 Incomplete(Option<io::Error>),
336 #[display(fmt = "Can not decode content-encoding.")]
338 EncodingCorrupted,
339 #[display(fmt = "A payload reached size limit.")]
341 Overflow,
342 #[display(fmt = "A payload length is unknown.")]
344 UnknownLength,
345 #[display(fmt = "{}", _0)]
347 Http2Payload(h2::Error),
348 #[display(fmt = "{}", _0)]
350 Io(io::Error),
351}
352
353impl From<h2::Error> for PayloadError {
354 fn from(err: h2::Error) -> Self {
355 PayloadError::Http2Payload(err)
356 }
357}
358
359impl From<Option<io::Error>> for PayloadError {
360 fn from(err: Option<io::Error>) -> Self {
361 PayloadError::Incomplete(err)
362 }
363}
364
365impl From<io::Error> for PayloadError {
366 fn from(err: io::Error) -> Self {
367 PayloadError::Incomplete(Some(err))
368 }
369}
370
371impl From<BlockingError<io::Error>> for PayloadError {
372 fn from(err: BlockingError<io::Error>) -> Self {
373 match err {
374 BlockingError::Error(e) => PayloadError::Io(e),
375 BlockingError::Canceled => PayloadError::Io(io::Error::new(
376 io::ErrorKind::Other,
377 "Operation is canceled",
378 )),
379 }
380 }
381}
382
383impl ResponseError for PayloadError {
388 fn status_code(&self) -> StatusCode {
389 match *self {
390 PayloadError::Overflow => StatusCode::PAYLOAD_TOO_LARGE,
391 _ => StatusCode::BAD_REQUEST,
392 }
393 }
394}
395
396impl ResponseError for crate::cookie::ParseError {
398 fn status_code(&self) -> StatusCode {
399 StatusCode::BAD_REQUEST
400 }
401}
402
403#[derive(Debug, Display, From)]
404pub enum DispatchError {
406 Service(Error),
408
409 Upgrade,
411
412 #[display(fmt = "IO error: {}", _0)]
415 Io(io::Error),
416
417 #[display(fmt = "Parse error: {}", _0)]
419 Parse(ParseError),
420
421 #[display(fmt = "{}", _0)]
423 H2(h2::Error),
424
425 #[display(fmt = "The first request did not complete within the specified timeout")]
427 SlowRequestTimeout,
428
429 #[display(fmt = "Connection shutdown timeout")]
431 DisconnectTimeout,
432
433 #[display(fmt = "Task is completed but request's payload is not consumed")]
435 PayloadIsNotConsumed,
436
437 #[display(fmt = "Malformed request")]
439 MalformedRequest,
440
441 #[display(fmt = "Internal error")]
443 InternalError,
444
445 #[display(fmt = "Unknown error")]
447 Unknown,
448}
449
450#[derive(PartialEq, Debug, Display)]
452pub enum ContentTypeError {
453 #[display(fmt = "Can not parse content type")]
455 ParseError,
456 #[display(fmt = "Unknown content encoding")]
458 UnknownEncoding,
459}
460
461impl ResponseError for ContentTypeError {
463 fn status_code(&self) -> StatusCode {
464 StatusCode::BAD_REQUEST
465 }
466}
467
468impl<E, U: Encoder + Decoder> ResponseError for FramedDispatcherError<E, U>
469where
470 E: fmt::Debug + fmt::Display,
471 <U as Encoder>::Error: fmt::Debug,
472 <U as Decoder>::Error: fmt::Debug,
473{
474}
475
476pub struct InternalError<T> {
491 cause: T,
492 status: InternalErrorType,
493}
494
495enum InternalErrorType {
496 Status(StatusCode),
497 Response(RefCell<Option<Response>>),
498}
499
500impl<T> InternalError<T> {
501 pub fn new(cause: T, status: StatusCode) -> Self {
503 InternalError {
504 cause,
505 status: InternalErrorType::Status(status),
506 }
507 }
508
509 pub fn from_response(cause: T, response: Response) -> Self {
511 InternalError {
512 cause,
513 status: InternalErrorType::Response(RefCell::new(Some(response))),
514 }
515 }
516}
517
518impl<T> fmt::Debug for InternalError<T>
519where
520 T: fmt::Debug + 'static,
521{
522 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
523 fmt::Debug::fmt(&self.cause, f)
524 }
525}
526
527impl<T> fmt::Display for InternalError<T>
528where
529 T: fmt::Display + 'static,
530{
531 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
532 fmt::Display::fmt(&self.cause, f)
533 }
534}
535
536impl<T> ResponseError for InternalError<T>
537where
538 T: fmt::Debug + fmt::Display + 'static,
539{
540 fn status_code(&self) -> StatusCode {
541 match self.status {
542 InternalErrorType::Status(st) => st,
543 InternalErrorType::Response(ref resp) => {
544 if let Some(resp) = resp.borrow().as_ref() {
545 resp.head().status
546 } else {
547 StatusCode::INTERNAL_SERVER_ERROR
548 }
549 }
550 }
551 }
552
553 fn error_response(&self) -> Response {
554 match self.status {
555 InternalErrorType::Status(st) => {
556 let mut res = Response::new(st);
557 let mut buf = BytesMut::new();
558 let _ = write!(Writer(&mut buf), "{}", self);
559 res.headers_mut().insert(
560 header::CONTENT_TYPE,
561 header::HeaderValue::from_static("text/plain; charset=utf-8"),
562 );
563 res.set_body(Body::from(buf))
564 }
565 InternalErrorType::Response(ref resp) => {
566 if let Some(resp) = resp.borrow_mut().take() {
567 resp
568 } else {
569 Response::new(StatusCode::INTERNAL_SERVER_ERROR)
570 }
571 }
572 }
573 }
574}
575
576#[allow(non_snake_case)]
579pub fn ErrorBadRequest<T>(err: T) -> Error
580where
581 T: fmt::Debug + fmt::Display + 'static,
582{
583 InternalError::new(err, StatusCode::BAD_REQUEST).into()
584}
585
586#[allow(non_snake_case)]
589pub fn ErrorUnauthorized<T>(err: T) -> Error
590where
591 T: fmt::Debug + fmt::Display + 'static,
592{
593 InternalError::new(err, StatusCode::UNAUTHORIZED).into()
594}
595
596#[allow(non_snake_case)]
599pub fn ErrorPaymentRequired<T>(err: T) -> Error
600where
601 T: fmt::Debug + fmt::Display + 'static,
602{
603 InternalError::new(err, StatusCode::PAYMENT_REQUIRED).into()
604}
605
606#[allow(non_snake_case)]
609pub fn ErrorForbidden<T>(err: T) -> Error
610where
611 T: fmt::Debug + fmt::Display + 'static,
612{
613 InternalError::new(err, StatusCode::FORBIDDEN).into()
614}
615
616#[allow(non_snake_case)]
619pub fn ErrorNotFound<T>(err: T) -> Error
620where
621 T: fmt::Debug + fmt::Display + 'static,
622{
623 InternalError::new(err, StatusCode::NOT_FOUND).into()
624}
625
626#[allow(non_snake_case)]
629pub fn ErrorMethodNotAllowed<T>(err: T) -> Error
630where
631 T: fmt::Debug + fmt::Display + 'static,
632{
633 InternalError::new(err, StatusCode::METHOD_NOT_ALLOWED).into()
634}
635
636#[allow(non_snake_case)]
639pub fn ErrorNotAcceptable<T>(err: T) -> Error
640where
641 T: fmt::Debug + fmt::Display + 'static,
642{
643 InternalError::new(err, StatusCode::NOT_ACCEPTABLE).into()
644}
645
646#[allow(non_snake_case)]
649pub fn ErrorProxyAuthenticationRequired<T>(err: T) -> Error
650where
651 T: fmt::Debug + fmt::Display + 'static,
652{
653 InternalError::new(err, StatusCode::PROXY_AUTHENTICATION_REQUIRED).into()
654}
655
656#[allow(non_snake_case)]
659pub fn ErrorRequestTimeout<T>(err: T) -> Error
660where
661 T: fmt::Debug + fmt::Display + 'static,
662{
663 InternalError::new(err, StatusCode::REQUEST_TIMEOUT).into()
664}
665
666#[allow(non_snake_case)]
669pub fn ErrorConflict<T>(err: T) -> Error
670where
671 T: fmt::Debug + fmt::Display + 'static,
672{
673 InternalError::new(err, StatusCode::CONFLICT).into()
674}
675
676#[allow(non_snake_case)]
679pub fn ErrorGone<T>(err: T) -> Error
680where
681 T: fmt::Debug + fmt::Display + 'static,
682{
683 InternalError::new(err, StatusCode::GONE).into()
684}
685
686#[allow(non_snake_case)]
689pub fn ErrorLengthRequired<T>(err: T) -> Error
690where
691 T: fmt::Debug + fmt::Display + 'static,
692{
693 InternalError::new(err, StatusCode::LENGTH_REQUIRED).into()
694}
695
696#[allow(non_snake_case)]
699pub fn ErrorPayloadTooLarge<T>(err: T) -> Error
700where
701 T: fmt::Debug + fmt::Display + 'static,
702{
703 InternalError::new(err, StatusCode::PAYLOAD_TOO_LARGE).into()
704}
705
706#[allow(non_snake_case)]
709pub fn ErrorUriTooLong<T>(err: T) -> Error
710where
711 T: fmt::Debug + fmt::Display + 'static,
712{
713 InternalError::new(err, StatusCode::URI_TOO_LONG).into()
714}
715
716#[allow(non_snake_case)]
719pub fn ErrorUnsupportedMediaType<T>(err: T) -> Error
720where
721 T: fmt::Debug + fmt::Display + 'static,
722{
723 InternalError::new(err, StatusCode::UNSUPPORTED_MEDIA_TYPE).into()
724}
725
726#[allow(non_snake_case)]
729pub fn ErrorRangeNotSatisfiable<T>(err: T) -> Error
730where
731 T: fmt::Debug + fmt::Display + 'static,
732{
733 InternalError::new(err, StatusCode::RANGE_NOT_SATISFIABLE).into()
734}
735
736#[allow(non_snake_case)]
739pub fn ErrorImATeapot<T>(err: T) -> Error
740where
741 T: fmt::Debug + fmt::Display + 'static,
742{
743 InternalError::new(err, StatusCode::IM_A_TEAPOT).into()
744}
745
746#[allow(non_snake_case)]
749pub fn ErrorMisdirectedRequest<T>(err: T) -> Error
750where
751 T: fmt::Debug + fmt::Display + 'static,
752{
753 InternalError::new(err, StatusCode::MISDIRECTED_REQUEST).into()
754}
755
756#[allow(non_snake_case)]
759pub fn ErrorUnprocessableEntity<T>(err: T) -> Error
760where
761 T: fmt::Debug + fmt::Display + 'static,
762{
763 InternalError::new(err, StatusCode::UNPROCESSABLE_ENTITY).into()
764}
765
766#[allow(non_snake_case)]
769pub fn ErrorLocked<T>(err: T) -> Error
770where
771 T: fmt::Debug + fmt::Display + 'static,
772{
773 InternalError::new(err, StatusCode::LOCKED).into()
774}
775
776#[allow(non_snake_case)]
779pub fn ErrorFailedDependency<T>(err: T) -> Error
780where
781 T: fmt::Debug + fmt::Display + 'static,
782{
783 InternalError::new(err, StatusCode::FAILED_DEPENDENCY).into()
784}
785
786#[allow(non_snake_case)]
789pub fn ErrorUpgradeRequired<T>(err: T) -> Error
790where
791 T: fmt::Debug + fmt::Display + 'static,
792{
793 InternalError::new(err, StatusCode::UPGRADE_REQUIRED).into()
794}
795
796#[allow(non_snake_case)]
799pub fn ErrorPreconditionFailed<T>(err: T) -> Error
800where
801 T: fmt::Debug + fmt::Display + 'static,
802{
803 InternalError::new(err, StatusCode::PRECONDITION_FAILED).into()
804}
805
806#[allow(non_snake_case)]
809pub fn ErrorPreconditionRequired<T>(err: T) -> Error
810where
811 T: fmt::Debug + fmt::Display + 'static,
812{
813 InternalError::new(err, StatusCode::PRECONDITION_REQUIRED).into()
814}
815
816#[allow(non_snake_case)]
819pub fn ErrorTooManyRequests<T>(err: T) -> Error
820where
821 T: fmt::Debug + fmt::Display + 'static,
822{
823 InternalError::new(err, StatusCode::TOO_MANY_REQUESTS).into()
824}
825
826#[allow(non_snake_case)]
829pub fn ErrorRequestHeaderFieldsTooLarge<T>(err: T) -> Error
830where
831 T: fmt::Debug + fmt::Display + 'static,
832{
833 InternalError::new(err, StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE).into()
834}
835
836#[allow(non_snake_case)]
839pub fn ErrorUnavailableForLegalReasons<T>(err: T) -> Error
840where
841 T: fmt::Debug + fmt::Display + 'static,
842{
843 InternalError::new(err, StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS).into()
844}
845
846#[allow(non_snake_case)]
849pub fn ErrorExpectationFailed<T>(err: T) -> Error
850where
851 T: fmt::Debug + fmt::Display + 'static,
852{
853 InternalError::new(err, StatusCode::EXPECTATION_FAILED).into()
854}
855
856#[allow(non_snake_case)]
859pub fn ErrorInternalServerError<T>(err: T) -> Error
860where
861 T: fmt::Debug + fmt::Display + 'static,
862{
863 InternalError::new(err, StatusCode::INTERNAL_SERVER_ERROR).into()
864}
865
866#[allow(non_snake_case)]
869pub fn ErrorNotImplemented<T>(err: T) -> Error
870where
871 T: fmt::Debug + fmt::Display + 'static,
872{
873 InternalError::new(err, StatusCode::NOT_IMPLEMENTED).into()
874}
875
876#[allow(non_snake_case)]
879pub fn ErrorBadGateway<T>(err: T) -> Error
880where
881 T: fmt::Debug + fmt::Display + 'static,
882{
883 InternalError::new(err, StatusCode::BAD_GATEWAY).into()
884}
885
886#[allow(non_snake_case)]
889pub fn ErrorServiceUnavailable<T>(err: T) -> Error
890where
891 T: fmt::Debug + fmt::Display + 'static,
892{
893 InternalError::new(err, StatusCode::SERVICE_UNAVAILABLE).into()
894}
895
896#[allow(non_snake_case)]
899pub fn ErrorGatewayTimeout<T>(err: T) -> Error
900where
901 T: fmt::Debug + fmt::Display + 'static,
902{
903 InternalError::new(err, StatusCode::GATEWAY_TIMEOUT).into()
904}
905
906#[allow(non_snake_case)]
909pub fn ErrorHttpVersionNotSupported<T>(err: T) -> Error
910where
911 T: fmt::Debug + fmt::Display + 'static,
912{
913 InternalError::new(err, StatusCode::HTTP_VERSION_NOT_SUPPORTED).into()
914}
915
916#[allow(non_snake_case)]
919pub fn ErrorVariantAlsoNegotiates<T>(err: T) -> Error
920where
921 T: fmt::Debug + fmt::Display + 'static,
922{
923 InternalError::new(err, StatusCode::VARIANT_ALSO_NEGOTIATES).into()
924}
925
926#[allow(non_snake_case)]
929pub fn ErrorInsufficientStorage<T>(err: T) -> Error
930where
931 T: fmt::Debug + fmt::Display + 'static,
932{
933 InternalError::new(err, StatusCode::INSUFFICIENT_STORAGE).into()
934}
935
936#[allow(non_snake_case)]
939pub fn ErrorLoopDetected<T>(err: T) -> Error
940where
941 T: fmt::Debug + fmt::Display + 'static,
942{
943 InternalError::new(err, StatusCode::LOOP_DETECTED).into()
944}
945
946#[allow(non_snake_case)]
949pub fn ErrorNotExtended<T>(err: T) -> Error
950where
951 T: fmt::Debug + fmt::Display + 'static,
952{
953 InternalError::new(err, StatusCode::NOT_EXTENDED).into()
954}
955
956#[allow(non_snake_case)]
959pub fn ErrorNetworkAuthenticationRequired<T>(err: T) -> Error
960where
961 T: fmt::Debug + fmt::Display + 'static,
962{
963 InternalError::new(err, StatusCode::NETWORK_AUTHENTICATION_REQUIRED).into()
964}
965
966#[cfg(feature = "failure")]
967impl ResponseError for fail_ure::Error {}
969
970#[cfg(test)]
971mod tests {
972 use super::*;
973 use http::{Error as HttpError, StatusCode};
974 use httparse;
975 use std::io;
976
977 #[test]
978 fn test_into_response() {
979 let resp: Response = ParseError::Incomplete.error_response();
980 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
981
982 let err: HttpError = StatusCode::from_u16(10000).err().unwrap().into();
983 let resp: Response = err.error_response();
984 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
985 }
986
987 #[test]
988 fn test_cookie_parse() {
989 let resp: Response = CookieParseError::EmptyName.error_response();
990 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
991 }
992
993 #[test]
994 fn test_as_response() {
995 let orig = io::Error::new(io::ErrorKind::Other, "other");
996 let e: Error = ParseError::Io(orig).into();
997 assert_eq!(format!("{}", e.as_response_error()), "IO error: other");
998 }
999
1000 #[test]
1001 fn test_error_cause() {
1002 let orig = io::Error::new(io::ErrorKind::Other, "other");
1003 let desc = orig.to_string();
1004 let e = Error::from(orig);
1005 assert_eq!(format!("{}", e.as_response_error()), desc);
1006 }
1007
1008 #[test]
1009 fn test_error_display() {
1010 let orig = io::Error::new(io::ErrorKind::Other, "other");
1011 let desc = orig.to_string();
1012 let e = Error::from(orig);
1013 assert_eq!(format!("{}", e), desc);
1014 }
1015
1016 #[test]
1017 fn test_error_http_response() {
1018 let orig = io::Error::new(io::ErrorKind::Other, "other");
1019 let e = Error::from(orig);
1020 let resp: Response = e.into();
1021 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
1022 }
1023
1024 #[test]
1025 fn test_payload_error() {
1026 let err: PayloadError =
1027 io::Error::new(io::ErrorKind::Other, "ParseError").into();
1028 assert!(format!("{}", err).contains("ParseError"));
1029
1030 let err = PayloadError::Incomplete(None);
1031 assert_eq!(
1032 format!("{}", err),
1033 "A payload reached EOF, but is not complete. With error: None"
1034 );
1035 }
1036
1037 macro_rules! from {
1038 ($from:expr => $error:pat) => {
1039 match ParseError::from($from) {
1040 e @ $error => {
1041 assert!(format!("{}", e).len() >= 5);
1042 }
1043 e => unreachable!("{:?}", e),
1044 }
1045 };
1046 }
1047
1048 macro_rules! from_and_cause {
1049 ($from:expr => $error:pat) => {
1050 match ParseError::from($from) {
1051 e @ $error => {
1052 let desc = format!("{}", e);
1053 assert_eq!(desc, format!("IO error: {}", $from));
1054 }
1055 _ => unreachable!("{:?}", $from),
1056 }
1057 };
1058 }
1059
1060 #[test]
1061 fn test_from() {
1062 from_and_cause!(io::Error::new(io::ErrorKind::Other, "other") => ParseError::Io(..));
1063 from!(httparse::Error::HeaderName => ParseError::Header);
1064 from!(httparse::Error::HeaderName => ParseError::Header);
1065 from!(httparse::Error::HeaderValue => ParseError::Header);
1066 from!(httparse::Error::NewLine => ParseError::Header);
1067 from!(httparse::Error::Status => ParseError::Status);
1068 from!(httparse::Error::Token => ParseError::Header);
1069 from!(httparse::Error::TooManyHeaders => ParseError::TooLarge);
1070 from!(httparse::Error::Version => ParseError::Version);
1071 }
1072
1073 #[test]
1074 fn test_internal_error() {
1075 let err =
1076 InternalError::from_response(ParseError::Method, Response::Ok().into());
1077 let resp: Response = err.error_response();
1078 assert_eq!(resp.status(), StatusCode::OK);
1079 }
1080
1081 #[test]
1082 fn test_error_casting() {
1083 let err = PayloadError::Overflow;
1084 let resp_err: &dyn ResponseError = &err;
1085 let err = resp_err.downcast_ref::<PayloadError>().unwrap();
1086 assert_eq!(err.to_string(), "A payload reached size limit.");
1087 let not_err = resp_err.downcast_ref::<ContentTypeError>();
1088 assert!(not_err.is_none());
1089 }
1090
1091 #[test]
1092 fn test_error_helpers() {
1093 let r: Response = ErrorBadRequest("err").into();
1094 assert_eq!(r.status(), StatusCode::BAD_REQUEST);
1095
1096 let r: Response = ErrorUnauthorized("err").into();
1097 assert_eq!(r.status(), StatusCode::UNAUTHORIZED);
1098
1099 let r: Response = ErrorPaymentRequired("err").into();
1100 assert_eq!(r.status(), StatusCode::PAYMENT_REQUIRED);
1101
1102 let r: Response = ErrorForbidden("err").into();
1103 assert_eq!(r.status(), StatusCode::FORBIDDEN);
1104
1105 let r: Response = ErrorNotFound("err").into();
1106 assert_eq!(r.status(), StatusCode::NOT_FOUND);
1107
1108 let r: Response = ErrorMethodNotAllowed("err").into();
1109 assert_eq!(r.status(), StatusCode::METHOD_NOT_ALLOWED);
1110
1111 let r: Response = ErrorNotAcceptable("err").into();
1112 assert_eq!(r.status(), StatusCode::NOT_ACCEPTABLE);
1113
1114 let r: Response = ErrorProxyAuthenticationRequired("err").into();
1115 assert_eq!(r.status(), StatusCode::PROXY_AUTHENTICATION_REQUIRED);
1116
1117 let r: Response = ErrorRequestTimeout("err").into();
1118 assert_eq!(r.status(), StatusCode::REQUEST_TIMEOUT);
1119
1120 let r: Response = ErrorConflict("err").into();
1121 assert_eq!(r.status(), StatusCode::CONFLICT);
1122
1123 let r: Response = ErrorGone("err").into();
1124 assert_eq!(r.status(), StatusCode::GONE);
1125
1126 let r: Response = ErrorLengthRequired("err").into();
1127 assert_eq!(r.status(), StatusCode::LENGTH_REQUIRED);
1128
1129 let r: Response = ErrorPreconditionFailed("err").into();
1130 assert_eq!(r.status(), StatusCode::PRECONDITION_FAILED);
1131
1132 let r: Response = ErrorPayloadTooLarge("err").into();
1133 assert_eq!(r.status(), StatusCode::PAYLOAD_TOO_LARGE);
1134
1135 let r: Response = ErrorUriTooLong("err").into();
1136 assert_eq!(r.status(), StatusCode::URI_TOO_LONG);
1137
1138 let r: Response = ErrorUnsupportedMediaType("err").into();
1139 assert_eq!(r.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE);
1140
1141 let r: Response = ErrorRangeNotSatisfiable("err").into();
1142 assert_eq!(r.status(), StatusCode::RANGE_NOT_SATISFIABLE);
1143
1144 let r: Response = ErrorExpectationFailed("err").into();
1145 assert_eq!(r.status(), StatusCode::EXPECTATION_FAILED);
1146
1147 let r: Response = ErrorImATeapot("err").into();
1148 assert_eq!(r.status(), StatusCode::IM_A_TEAPOT);
1149
1150 let r: Response = ErrorMisdirectedRequest("err").into();
1151 assert_eq!(r.status(), StatusCode::MISDIRECTED_REQUEST);
1152
1153 let r: Response = ErrorUnprocessableEntity("err").into();
1154 assert_eq!(r.status(), StatusCode::UNPROCESSABLE_ENTITY);
1155
1156 let r: Response = ErrorLocked("err").into();
1157 assert_eq!(r.status(), StatusCode::LOCKED);
1158
1159 let r: Response = ErrorFailedDependency("err").into();
1160 assert_eq!(r.status(), StatusCode::FAILED_DEPENDENCY);
1161
1162 let r: Response = ErrorUpgradeRequired("err").into();
1163 assert_eq!(r.status(), StatusCode::UPGRADE_REQUIRED);
1164
1165 let r: Response = ErrorPreconditionRequired("err").into();
1166 assert_eq!(r.status(), StatusCode::PRECONDITION_REQUIRED);
1167
1168 let r: Response = ErrorTooManyRequests("err").into();
1169 assert_eq!(r.status(), StatusCode::TOO_MANY_REQUESTS);
1170
1171 let r: Response = ErrorRequestHeaderFieldsTooLarge("err").into();
1172 assert_eq!(r.status(), StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE);
1173
1174 let r: Response = ErrorUnavailableForLegalReasons("err").into();
1175 assert_eq!(r.status(), StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS);
1176
1177 let r: Response = ErrorInternalServerError("err").into();
1178 assert_eq!(r.status(), StatusCode::INTERNAL_SERVER_ERROR);
1179
1180 let r: Response = ErrorNotImplemented("err").into();
1181 assert_eq!(r.status(), StatusCode::NOT_IMPLEMENTED);
1182
1183 let r: Response = ErrorBadGateway("err").into();
1184 assert_eq!(r.status(), StatusCode::BAD_GATEWAY);
1185
1186 let r: Response = ErrorServiceUnavailable("err").into();
1187 assert_eq!(r.status(), StatusCode::SERVICE_UNAVAILABLE);
1188
1189 let r: Response = ErrorGatewayTimeout("err").into();
1190 assert_eq!(r.status(), StatusCode::GATEWAY_TIMEOUT);
1191
1192 let r: Response = ErrorHttpVersionNotSupported("err").into();
1193 assert_eq!(r.status(), StatusCode::HTTP_VERSION_NOT_SUPPORTED);
1194
1195 let r: Response = ErrorVariantAlsoNegotiates("err").into();
1196 assert_eq!(r.status(), StatusCode::VARIANT_ALSO_NEGOTIATES);
1197
1198 let r: Response = ErrorInsufficientStorage("err").into();
1199 assert_eq!(r.status(), StatusCode::INSUFFICIENT_STORAGE);
1200
1201 let r: Response = ErrorLoopDetected("err").into();
1202 assert_eq!(r.status(), StatusCode::LOOP_DETECTED);
1203
1204 let r: Response = ErrorNotExtended("err").into();
1205 assert_eq!(r.status(), StatusCode::NOT_EXTENDED);
1206
1207 let r: Response = ErrorNetworkAuthenticationRequired("err").into();
1208 assert_eq!(r.status(), StatusCode::NETWORK_AUTHENTICATION_REQUIRED);
1209 }
1210}