1use std::{cell::RefCell, error::Error, fmt, io::Write};
3
4pub use ntex_http::error::Error as HttpError;
5pub use serde_json::error::Error as JsonError;
6pub use urly::InvalidUrl as UrlParseError;
7
8use crate::http::body::Body;
9use crate::http::{StatusCode, error, header};
10use crate::util::{BytesMut, Either};
11
12pub use crate::http::error::BlockingError;
13pub use crate::web::error_default::DefaultError;
14
15use super::HttpResponse;
16
17pub trait WebResponseError<St, Err>: Error + 'static {
19 fn error_response(&self, _: &St) -> HttpResponse {
23 HttpResponse::render_with(StatusCode::INTERNAL_SERVER_ERROR, &self)
24 }
25
26 fn into(self) -> Box<dyn WebResponseError<St, Err>>
31 where
32 Self: Sized,
33 {
34 Box::new(self)
35 }
36}
37
38pub struct WebError<St = (), Err = DefaultError>(pub(crate) Box<dyn WebResponseError<St, Err>>);
47
48impl<St: 'static, Err: 'static> WebError<St, Err> {
49 pub fn from_err<E: WebResponseError<St, Err>>(err: E) -> Self {
51 Self(err.into())
52 }
53}
54
55impl<St: 'static, Err: 'static> WebResponseError<St, Err> for WebError<St, Err> {
56 fn error_response(&self, st: &St) -> HttpResponse {
57 self.0.error_response(st)
58 }
59
60 fn into(self) -> Box<dyn WebResponseError<St, Err>> {
61 self.0
62 }
63}
64
65impl<St, Err> Error for WebError<St, Err> {
66 fn source(&self) -> Option<&(dyn Error + 'static)> {
67 self.0.source()
68 }
69}
70
71impl<St, Err> crate::http::error::ResponseError for WebError<St, Err> {
72 fn error_response(&self) -> HttpResponse {
73 HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
74 }
75}
76
77impl<St, Err> fmt::Display for WebError<St, Err> {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 write!(f, "{}", self.0)
80 }
81}
82
83impl<St, Err> fmt::Debug for WebError<St, Err> {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 write!(f, "web::WebError({})", self.0)
86 }
87}
88
89impl<E, St, Err> WebResponseError<St, Err> for crate::error::Error<E>
92where
93 E: WebResponseError<St, Err> + Clone,
94{
95 fn error_response(&self, st: &St) -> HttpResponse {
96 (**self).error_response(st)
97 }
98}
99
100impl<St, Err> WebResponseError<St, Err> for std::convert::Infallible {}
103
104impl<St, Err, A, B> WebResponseError<St, Err> for Either<A, B>
105where
106 A: WebResponseError<St, Err>,
107 B: WebResponseError<St, Err>,
108{
109 fn error_response(&self, st: &St) -> HttpResponse {
110 match self {
111 Either::Left(a) => a.error_response(st),
112 Either::Right(b) => b.error_response(st),
113 }
114 }
115}
116
117#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
119pub enum UrlGenerationError {
120 #[error("Resource not found")]
122 ResourceNotFound,
123 #[error("Not all path pattern covered")]
125 NotEnoughElements,
126 #[error("{0}")]
128 ParseError(
129 #[from]
130 #[source]
131 UrlParseError,
132 ),
133}
134
135#[derive(Debug, thiserror::Error)]
137pub enum UrlencodedError {
138 #[error("Cannot decode chunked transfer encoding")]
140 Chunked,
141 #[error(
143 "Urlencoded payload size is bigger ({size} bytes) than allowed (default: {limit} bytes)"
144 )]
145 Overflow {
146 size: usize,
148 limit: usize,
150 },
151 #[error("Payload size is unknown")]
153 UnknownLength,
154 #[error("Content type error")]
156 ContentType,
157 #[error("Parse error")]
159 Parse,
160 #[error("Error that occur during reading payload: {0}")]
162 Payload(
163 #[from]
164 #[source]
165 error::PayloadError,
166 ),
167}
168
169#[derive(Debug, thiserror::Error)]
171pub enum JsonPayloadError {
172 #[error("Json payload size is bigger than allowed")]
174 Overflow,
175 #[error("Content type error")]
177 ContentType,
178 #[error("Json deserialize error: {0}")]
180 Deserialize(
181 #[from]
182 #[source]
183 serde_json::error::Error,
184 ),
185 #[error("Error that occur during reading payload: {0}")]
187 Payload(
188 #[from]
189 #[source]
190 error::PayloadError,
191 ),
192}
193
194#[derive(Debug, thiserror::Error)]
196pub enum PathError {
197 #[error("Path deserialize error: {0}")]
199 Deserialize(
200 #[from]
201 #[source]
202 serde::de::value::Error,
203 ),
204}
205
206#[derive(Debug, thiserror::Error)]
208pub enum QueryPayloadError {
209 #[error("Query deserialize error: {0}")]
211 Deserialize(
212 #[from]
213 #[source]
214 serde::de::value::Error,
215 ),
216}
217
218#[derive(Debug, thiserror::Error)]
222pub enum PayloadError {
223 #[error("{0:?}")]
225 Http(
226 #[from]
227 #[source]
228 error::HttpError,
229 ),
230 #[error("{0}")]
232 Payload(
233 #[from]
234 #[source]
235 error::PayloadError,
236 ),
237 #[error("{0}")]
239 ContentType(
240 #[from]
241 #[source]
242 error::ContentTypeError,
243 ),
244 #[error("Cannot decode body")]
246 Decoding,
247}
248
249pub struct InternalError<T> {
271 cause: T,
272 status: InternalErrorType,
273}
274
275enum InternalErrorType {
276 Status(StatusCode),
277 Response(RefCell<Option<HttpResponse>>),
278}
279
280impl<T> InternalError<T> {
281 pub fn default(cause: T, status: StatusCode) -> Self {
283 InternalError {
284 cause,
285 status: InternalErrorType::Status(status),
286 }
287 }
288}
289
290impl<T> InternalError<T> {
291 pub fn new(cause: T, status: StatusCode) -> Self {
293 InternalError {
294 cause,
295 status: InternalErrorType::Status(status),
296 }
297 }
298
299 pub fn from_response(cause: T, response: HttpResponse) -> Self {
301 InternalError {
302 cause,
303 status: InternalErrorType::Response(RefCell::new(Some(response))),
304 }
305 }
306}
307
308impl<T> fmt::Debug for InternalError<T>
309where
310 T: fmt::Debug + 'static,
311{
312 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
313 write!(f, "web::InternalError({:?})", self.cause)
314 }
315}
316
317impl<T> fmt::Display for InternalError<T>
318where
319 T: fmt::Display + 'static,
320{
321 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
322 fmt::Display::fmt(&self.cause, f)
323 }
324}
325
326impl<T: fmt::Display + fmt::Debug + 'static> std::error::Error for InternalError<T> {}
327
328impl<St, Err, T> WebResponseError<St, Err> for InternalError<T>
329where
330 T: fmt::Debug + fmt::Display + 'static,
331{
332 fn error_response(&self, _: &St) -> HttpResponse {
333 crate::http::error::ResponseError::error_response(self)
334 }
335}
336
337impl<T> crate::http::error::ResponseError for InternalError<T>
338where
339 T: fmt::Debug + fmt::Display + 'static,
340{
341 fn error_response(&self) -> HttpResponse {
342 match self.status {
343 InternalErrorType::Status(st) => {
344 let mut res = HttpResponse::new(st);
345 let mut buf = BytesMut::new();
346 let _ = write!(&mut buf, "{self}");
347 res.headers_mut().insert(
348 header::CONTENT_TYPE,
349 header::HeaderValue::from_static("text/plain; charset=utf-8"),
350 );
351 res.set_body(Body::from(buf))
352 }
353 InternalErrorType::Response(ref resp) => {
354 if let Some(resp) = resp.borrow_mut().take() {
355 resp
356 } else {
357 HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
358 }
359 }
360 }
361 }
362}
363
364#[allow(non_snake_case)]
367pub fn ErrorBadRequest<T>(err: T) -> InternalError<T>
368where
369 T: fmt::Debug + fmt::Display + 'static,
370{
371 InternalError::new(err, StatusCode::BAD_REQUEST)
372}
373
374#[allow(non_snake_case)]
377pub fn ErrorUnauthorized<T>(err: T) -> InternalError<T>
378where
379 T: fmt::Debug + fmt::Display + 'static,
380{
381 InternalError::new(err, StatusCode::UNAUTHORIZED)
382}
383
384#[allow(non_snake_case)]
387pub fn ErrorPaymentRequired<T>(err: T) -> InternalError<T>
388where
389 T: fmt::Debug + fmt::Display + 'static,
390{
391 InternalError::new(err, StatusCode::PAYMENT_REQUIRED)
392}
393
394#[allow(non_snake_case)]
397pub fn ErrorForbidden<T>(err: T) -> InternalError<T>
398where
399 T: fmt::Debug + fmt::Display + 'static,
400{
401 InternalError::new(err, StatusCode::FORBIDDEN)
402}
403
404#[allow(non_snake_case)]
407pub fn ErrorNotFound<T>(err: T) -> InternalError<T>
408where
409 T: fmt::Debug + fmt::Display + 'static,
410{
411 InternalError::new(err, StatusCode::NOT_FOUND)
412}
413
414#[allow(non_snake_case)]
417pub fn ErrorMethodNotAllowed<T>(err: T) -> InternalError<T>
418where
419 T: fmt::Debug + fmt::Display + 'static,
420{
421 InternalError::new(err, StatusCode::METHOD_NOT_ALLOWED)
422}
423
424#[allow(non_snake_case)]
427pub fn ErrorNotAcceptable<T>(err: T) -> InternalError<T>
428where
429 T: fmt::Debug + fmt::Display + 'static,
430{
431 InternalError::new(err, StatusCode::NOT_ACCEPTABLE)
432}
433
434#[allow(non_snake_case)]
437pub fn ErrorProxyAuthenticationRequired<T>(err: T) -> InternalError<T>
438where
439 T: fmt::Debug + fmt::Display + 'static,
440{
441 InternalError::new(err, StatusCode::PROXY_AUTHENTICATION_REQUIRED)
442}
443
444#[allow(non_snake_case)]
447pub fn ErrorRequestTimeout<T>(err: T) -> InternalError<T>
448where
449 T: fmt::Debug + fmt::Display + 'static,
450{
451 InternalError::new(err, StatusCode::REQUEST_TIMEOUT)
452}
453
454#[allow(non_snake_case)]
457pub fn ErrorConflict<T>(err: T) -> InternalError<T>
458where
459 T: fmt::Debug + fmt::Display + 'static,
460{
461 InternalError::new(err, StatusCode::CONFLICT)
462}
463
464#[allow(non_snake_case)]
467pub fn ErrorGone<T>(err: T) -> InternalError<T>
468where
469 T: fmt::Debug + fmt::Display + 'static,
470{
471 InternalError::new(err, StatusCode::GONE)
472}
473
474#[allow(non_snake_case)]
477pub fn ErrorLengthRequired<T>(err: T) -> InternalError<T>
478where
479 T: fmt::Debug + fmt::Display + 'static,
480{
481 InternalError::new(err, StatusCode::LENGTH_REQUIRED)
482}
483
484#[allow(non_snake_case)]
487pub fn ErrorPayloadTooLarge<T>(err: T) -> InternalError<T>
488where
489 T: fmt::Debug + fmt::Display + 'static,
490{
491 InternalError::new(err, StatusCode::PAYLOAD_TOO_LARGE)
492}
493
494#[allow(non_snake_case)]
497pub fn ErrorUriTooLong<T>(err: T) -> InternalError<T>
498where
499 T: fmt::Debug + fmt::Display + 'static,
500{
501 InternalError::new(err, StatusCode::URI_TOO_LONG)
502}
503
504#[allow(non_snake_case)]
507pub fn ErrorUnsupportedMediaType<T>(err: T) -> InternalError<T>
508where
509 T: fmt::Debug + fmt::Display + 'static,
510{
511 InternalError::new(err, StatusCode::UNSUPPORTED_MEDIA_TYPE)
512}
513
514#[allow(non_snake_case)]
517pub fn ErrorRangeNotSatisfiable<T>(err: T) -> InternalError<T>
518where
519 T: fmt::Debug + fmt::Display + 'static,
520{
521 InternalError::new(err, StatusCode::RANGE_NOT_SATISFIABLE)
522}
523
524#[allow(non_snake_case)]
527pub fn ErrorImATeapot<T>(err: T) -> InternalError<T>
528where
529 T: fmt::Debug + fmt::Display + 'static,
530{
531 InternalError::new(err, StatusCode::IM_A_TEAPOT)
532}
533
534#[allow(non_snake_case)]
537pub fn ErrorMisdirectedRequest<T>(err: T) -> InternalError<T>
538where
539 T: fmt::Debug + fmt::Display + 'static,
540{
541 InternalError::new(err, StatusCode::MISDIRECTED_REQUEST)
542}
543
544#[allow(non_snake_case)]
547pub fn ErrorUnprocessableEntity<T>(err: T) -> InternalError<T>
548where
549 T: fmt::Debug + fmt::Display + 'static,
550{
551 InternalError::new(err, StatusCode::UNPROCESSABLE_ENTITY)
552}
553
554#[allow(non_snake_case)]
557pub fn ErrorLocked<T>(err: T) -> InternalError<T>
558where
559 T: fmt::Debug + fmt::Display + 'static,
560{
561 InternalError::new(err, StatusCode::LOCKED)
562}
563
564#[allow(non_snake_case)]
567pub fn ErrorFailedDependency<T>(err: T) -> InternalError<T>
568where
569 T: fmt::Debug + fmt::Display + 'static,
570{
571 InternalError::new(err, StatusCode::FAILED_DEPENDENCY)
572}
573
574#[allow(non_snake_case)]
577pub fn ErrorUpgradeRequired<T>(err: T) -> InternalError<T>
578where
579 T: fmt::Debug + fmt::Display + 'static,
580{
581 InternalError::new(err, StatusCode::UPGRADE_REQUIRED)
582}
583
584#[allow(non_snake_case)]
587pub fn ErrorPreconditionFailed<T>(err: T) -> InternalError<T>
588where
589 T: fmt::Debug + fmt::Display + 'static,
590{
591 InternalError::new(err, StatusCode::PRECONDITION_FAILED)
592}
593
594#[allow(non_snake_case)]
597pub fn ErrorPreconditionRequired<T>(err: T) -> InternalError<T>
598where
599 T: fmt::Debug + fmt::Display + 'static,
600{
601 InternalError::new(err, StatusCode::PRECONDITION_REQUIRED)
602}
603
604#[allow(non_snake_case)]
607pub fn ErrorTooManyRequests<T>(err: T) -> InternalError<T>
608where
609 T: fmt::Debug + fmt::Display + 'static,
610{
611 InternalError::new(err, StatusCode::TOO_MANY_REQUESTS)
612}
613
614#[allow(non_snake_case)]
617pub fn ErrorRequestHeaderFieldsTooLarge<T>(err: T) -> InternalError<T>
618where
619 T: fmt::Debug + fmt::Display + 'static,
620{
621 InternalError::new(err, StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE)
622}
623
624#[allow(non_snake_case)]
627pub fn ErrorUnavailableForLegalReasons<T>(err: T) -> InternalError<T>
628where
629 T: fmt::Debug + fmt::Display + 'static,
630{
631 InternalError::new(err, StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS)
632}
633
634#[allow(non_snake_case)]
637pub fn ErrorExpectationFailed<T>(err: T) -> InternalError<T>
638where
639 T: fmt::Debug + fmt::Display + 'static,
640{
641 InternalError::new(err, StatusCode::EXPECTATION_FAILED)
642}
643
644#[allow(non_snake_case)]
647pub fn ErrorInternalServerError<T>(err: T) -> InternalError<T>
648where
649 T: fmt::Debug + fmt::Display + 'static,
650{
651 InternalError::new(err, StatusCode::INTERNAL_SERVER_ERROR)
652}
653
654#[allow(non_snake_case)]
657pub fn ErrorNotImplemented<T>(err: T) -> InternalError<T>
658where
659 T: fmt::Debug + fmt::Display + 'static,
660{
661 InternalError::new(err, StatusCode::NOT_IMPLEMENTED)
662}
663
664#[allow(non_snake_case)]
667pub fn ErrorBadGateway<T>(err: T) -> InternalError<T>
668where
669 T: fmt::Debug + fmt::Display + 'static,
670{
671 InternalError::new(err, StatusCode::BAD_GATEWAY)
672}
673
674#[allow(non_snake_case)]
677pub fn ErrorServiceUnavailable<T>(err: T) -> InternalError<T>
678where
679 T: fmt::Debug + fmt::Display + 'static,
680{
681 InternalError::new(err, StatusCode::SERVICE_UNAVAILABLE)
682}
683
684#[allow(non_snake_case)]
687pub fn ErrorGatewayTimeout<T>(err: T) -> InternalError<T>
688where
689 T: fmt::Debug + fmt::Display + 'static,
690{
691 InternalError::new(err, StatusCode::GATEWAY_TIMEOUT)
692}
693
694#[allow(non_snake_case)]
697pub fn ErrorHttpVersionNotSupported<T>(err: T) -> InternalError<T>
698where
699 T: fmt::Debug + fmt::Display + 'static,
700{
701 InternalError::new(err, StatusCode::HTTP_VERSION_NOT_SUPPORTED)
702}
703
704#[allow(non_snake_case)]
707pub fn ErrorVariantAlsoNegotiates<T>(err: T) -> InternalError<T>
708where
709 T: fmt::Debug + fmt::Display + 'static,
710{
711 InternalError::new(err, StatusCode::VARIANT_ALSO_NEGOTIATES)
712}
713
714#[allow(non_snake_case)]
717pub fn ErrorInsufficientStorage<T>(err: T) -> InternalError<T>
718where
719 T: fmt::Debug + fmt::Display + 'static,
720{
721 InternalError::new(err, StatusCode::INSUFFICIENT_STORAGE)
722}
723
724#[allow(non_snake_case)]
727pub fn ErrorLoopDetected<T>(err: T) -> InternalError<T>
728where
729 T: fmt::Debug + fmt::Display + 'static,
730{
731 InternalError::new(err, StatusCode::LOOP_DETECTED)
732}
733
734#[allow(non_snake_case)]
737pub fn ErrorNotExtended<T>(err: T) -> InternalError<T>
738where
739 T: fmt::Debug + fmt::Display + 'static,
740{
741 InternalError::new(err, StatusCode::NOT_EXTENDED)
742}
743
744#[allow(non_snake_case)]
747pub fn ErrorNetworkAuthenticationRequired<T>(err: T) -> InternalError<T>
748where
749 T: fmt::Debug + fmt::Display + 'static,
750{
751 InternalError::new(err, StatusCode::NETWORK_AUTHENTICATION_REQUIRED)
752}
753
754#[cfg(test)]
755mod tests {
756 use std::io;
757
758 use super::*;
759 use crate::client::error::{ClientError, ConnectError};
760 use crate::{http, web::WebError};
761
762 #[test]
763 fn test_into_error() {
764 let e = WebError::<(), _>::from_err(UrlencodedError::UnknownLength);
765 let s = format!("{e}");
766 assert!(s.contains("Payload size is unknown"), "{}", s);
767 let s = format!("{e:?}");
768 assert!(s.contains("web::WebError"), "{}", s);
769
770 let res = crate::http::ResponseError::error_response(&e);
771 assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
772
773 let res = WebResponseError::<(), DefaultError>::error_response(
774 &UrlencodedError::UnknownLength,
775 &(),
776 );
777 assert_eq!(res.status(), StatusCode::LENGTH_REQUIRED);
778 }
779
780 #[test]
781 fn test_other_errors() {
782 use crate::util::timeout::TimeoutError;
783
784 let err = TimeoutError::<UrlencodedError>::Timeout;
785 assert_eq!(
786 WebResponseError::<(), DefaultError>::error_response(&err, &(),).status(),
787 StatusCode::GATEWAY_TIMEOUT
788 );
789
790 let err = TimeoutError::<UrlencodedError>::Service(UrlencodedError::Chunked);
791 assert_eq!(
792 WebResponseError::<(), DefaultError>::error_response(&err, &(),).status(),
793 StatusCode::BAD_REQUEST
794 );
795
796 let resp = WebResponseError::error_response(
797 &ClientError::Connect(ConnectError::SslIsNotSupported),
798 &(),
799 );
800 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
801
802 let resp = WebResponseError::error_response(&ClientError::Timeout, &());
803 assert_eq!(resp.status(), StatusCode::GATEWAY_TIMEOUT);
804
805 let resp = WebResponseError::error_response(&ClientError::Send(io::Error::other("x")), &());
806 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
807
808 #[cfg(feature = "cookie")]
809 {
810 let resp: HttpResponse =
811 WebResponseError::error_response(&coo_kie::ParseError::EmptyName, &());
812 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
813 }
814
815 let resp = WebResponseError::error_response(
816 &crate::http::error::ContentTypeError::ParseError,
817 &(),
818 );
819 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
820
821 let err = serde_urlencoded::from_str::<i32>("bad query").unwrap_err();
822 let resp = WebResponseError::error_response(&err, &());
823 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
824
825 let err = PayloadError::Decoding;
826 let resp = WebResponseError::error_response(&err, &());
827 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
828
829 #[allow(invalid_from_utf8)]
830 let err = std::str::from_utf8(b"\xF0").unwrap_err();
831 let resp = WebResponseError::error_response(&err, &());
832 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
833
834 let err = http::error::PayloadError::EncodingCorrupted;
835 let resp = WebResponseError::error_response(&err, &());
836 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
837 }
838
839 #[test]
840 fn test_either_error() {
841 let err: Either<ClientError, PayloadError> = Either::Left(ClientError::Timeout);
842 let resp = WebResponseError::error_response(&err, &());
843 assert_eq!(resp.status(), StatusCode::GATEWAY_TIMEOUT);
844
845 let err: Either<ClientError, PayloadError> = Either::Right(PayloadError::Decoding);
846 let resp = WebResponseError::error_response(&err, &());
847 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
848 }
849
850 #[test]
851 fn test_io_error() {
852 assert_eq!(
853 StatusCode::NOT_FOUND,
854 WebResponseError::error_response(&io::Error::new(io::ErrorKind::NotFound, ""), &(),)
855 .status(),
856 );
857 assert_eq!(
858 StatusCode::FORBIDDEN,
859 WebResponseError::error_response(
860 &io::Error::new(io::ErrorKind::PermissionDenied, ""),
861 &(),
862 )
863 .status(),
864 );
865 assert_eq!(
866 StatusCode::INTERNAL_SERVER_ERROR,
867 WebResponseError::error_response(&io::Error::other(""), &(),).status(),
868 );
869 }
870
871 #[test]
872 fn test_urlencoded_error() {
873 let resp: HttpResponse =
874 WebResponseError::error_response(&UrlencodedError::Overflow { size: 0, limit: 0 }, &());
875 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
876 let resp: HttpResponse =
877 WebResponseError::error_response(&UrlencodedError::UnknownLength, &());
878 assert_eq!(resp.status(), StatusCode::LENGTH_REQUIRED);
879 let resp: HttpResponse =
880 WebResponseError::error_response(&UrlencodedError::ContentType, &());
881 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
882 }
883
884 #[test]
885 fn test_json_payload_error() {
886 let resp: HttpResponse = WebResponseError::error_response(&JsonPayloadError::Overflow, &());
887 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
888 let resp: HttpResponse =
889 WebResponseError::error_response(&JsonPayloadError::ContentType, &());
890 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
891 }
892
893 #[test]
894 fn test_query_payload_error() {
895 let err = QueryPayloadError::Deserialize(
896 serde_urlencoded::from_str::<i32>("bad query").unwrap_err(),
897 );
898 let resp: HttpResponse = WebResponseError::error_response(&err, &());
899 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
900 }
901
902 #[test]
903 fn test_path_error() {
904 let err =
905 PathError::Deserialize(serde_urlencoded::from_str::<i32>("bad path").unwrap_err());
906 let resp: HttpResponse = WebResponseError::error_response(&err, &());
907 assert_eq!(resp.status(), StatusCode::NOT_FOUND);
908 }
909
910 #[test]
911 fn test_handshake_error() {
912 use crate::ws::error::HandshakeError;
913
914 let resp = WebResponseError::<_, DefaultError>::error_response(
915 &HandshakeError::GetMethodRequired,
916 &(),
917 );
918 assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
919 let resp = WebResponseError::<_, DefaultError>::error_response(
920 &HandshakeError::NoWebsocketUpgrade,
921 &(),
922 );
923 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
924 let resp = WebResponseError::<_, DefaultError>::error_response(
925 &HandshakeError::NoConnectionUpgrade,
926 &(),
927 );
928 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
929 let resp = WebResponseError::<_, DefaultError>::error_response(
930 &HandshakeError::NoVersionHeader,
931 &(),
932 );
933 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
934 let resp = WebResponseError::<_, DefaultError>::error_response(
935 &HandshakeError::UnsupportedVersion,
936 &(),
937 );
938 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
939 assert_eq!(
940 resp.headers().get(header::SEC_WEBSOCKET_VERSION).unwrap(),
941 "13"
942 );
943 let resp = WebResponseError::<_, DefaultError>::error_response(
944 &HandshakeError::BadWebsocketKey,
945 &(),
946 );
947 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
948 let resp = WebResponseError::<_, DefaultError>::error_response(
949 &HandshakeError::BadWebsocketProtocol,
950 &(),
951 );
952 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
953 }
954
955 #[test]
956 fn test_error_helpers() {
957 let err = ErrorBadRequest::<_>("err");
958 assert!(format!("{err:?}").contains("web::InternalError"));
959
960 let err: InternalError<_> =
961 InternalError::from_response("err", HttpResponse::BadRequest().build());
962 let r = WebResponseError::<_, DefaultError>::error_response(&err, &());
963 assert_eq!(r.status(), StatusCode::BAD_REQUEST);
964
965 let r =
966 WebResponseError::<_, DefaultError>::error_response(&ErrorBadRequest::<_>("err"), &());
967 assert_eq!(r.status(), StatusCode::BAD_REQUEST);
968
969 let r = WebResponseError::<_, DefaultError>::error_response(
970 &ErrorUnauthorized::<_>("err"),
971 &(),
972 );
973 assert_eq!(r.status(), StatusCode::UNAUTHORIZED);
974
975 let r = WebResponseError::<_, DefaultError>::error_response(
976 &ErrorPaymentRequired::<_>("err"),
977 &(),
978 );
979 assert_eq!(r.status(), StatusCode::PAYMENT_REQUIRED);
980
981 let r =
982 WebResponseError::<_, DefaultError>::error_response(&ErrorForbidden::<_>("err"), &());
983 assert_eq!(r.status(), StatusCode::FORBIDDEN);
984
985 let r =
986 WebResponseError::<_, DefaultError>::error_response(&ErrorNotFound::<_>("err"), &());
987 assert_eq!(r.status(), StatusCode::NOT_FOUND);
988
989 let r = WebResponseError::<_, DefaultError>::error_response(
990 &ErrorMethodNotAllowed::<_>("err"),
991 &(),
992 );
993 assert_eq!(r.status(), StatusCode::METHOD_NOT_ALLOWED);
994
995 let r = WebResponseError::<_, DefaultError>::error_response(
996 &ErrorNotAcceptable::<_>("err"),
997 &(),
998 );
999 assert_eq!(r.status(), StatusCode::NOT_ACCEPTABLE);
1000
1001 let r = WebResponseError::<_, DefaultError>::error_response(
1002 &ErrorProxyAuthenticationRequired::<_>("err"),
1003 &(),
1004 );
1005 assert_eq!(r.status(), StatusCode::PROXY_AUTHENTICATION_REQUIRED);
1006
1007 let r = WebResponseError::<_, DefaultError>::error_response(
1008 &ErrorRequestTimeout::<_>("err"),
1009 &(),
1010 );
1011 assert_eq!(r.status(), StatusCode::REQUEST_TIMEOUT);
1012
1013 let r =
1014 WebResponseError::<_, DefaultError>::error_response(&ErrorConflict::<_>("err"), &());
1015 assert_eq!(r.status(), StatusCode::CONFLICT);
1016
1017 let r = WebResponseError::<_, DefaultError>::error_response(&ErrorGone::<_>("err"), &());
1018 assert_eq!(r.status(), StatusCode::GONE);
1019
1020 let r = WebResponseError::<_, DefaultError>::error_response(
1021 &ErrorLengthRequired::<_>("err"),
1022 &(),
1023 );
1024 assert_eq!(r.status(), StatusCode::LENGTH_REQUIRED);
1025
1026 let r = WebResponseError::<_, DefaultError>::error_response(
1027 &ErrorPreconditionFailed::<_>("err"),
1028 &(),
1029 );
1030 assert_eq!(r.status(), StatusCode::PRECONDITION_FAILED);
1031
1032 let r = WebResponseError::<_, DefaultError>::error_response(
1033 &ErrorPayloadTooLarge::<_>("err"),
1034 &(),
1035 );
1036 assert_eq!(r.status(), StatusCode::PAYLOAD_TOO_LARGE);
1037
1038 let r =
1039 WebResponseError::<_, DefaultError>::error_response(&ErrorUriTooLong::<_>("err"), &());
1040 assert_eq!(r.status(), StatusCode::URI_TOO_LONG);
1041
1042 let r = WebResponseError::<_, DefaultError>::error_response(
1043 &ErrorUnsupportedMediaType::<_>("err"),
1044 &(),
1045 );
1046 assert_eq!(r.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE);
1047
1048 let r = WebResponseError::<_, DefaultError>::error_response(
1049 &ErrorRangeNotSatisfiable::<_>("err"),
1050 &(),
1051 );
1052 assert_eq!(r.status(), StatusCode::RANGE_NOT_SATISFIABLE);
1053
1054 let r = WebResponseError::<_, DefaultError>::error_response(
1055 &ErrorExpectationFailed::<_>("err"),
1056 &(),
1057 );
1058 assert_eq!(r.status(), StatusCode::EXPECTATION_FAILED);
1059
1060 let r =
1061 WebResponseError::<_, DefaultError>::error_response(&ErrorImATeapot::<_>("err"), &());
1062 assert_eq!(r.status(), StatusCode::IM_A_TEAPOT);
1063
1064 let r = WebResponseError::<_, DefaultError>::error_response(
1065 &ErrorMisdirectedRequest::<_>("err"),
1066 &(),
1067 );
1068 assert_eq!(r.status(), StatusCode::MISDIRECTED_REQUEST);
1069
1070 let r = WebResponseError::<_, DefaultError>::error_response(
1071 &ErrorUnprocessableEntity::<_>("err"),
1072 &(),
1073 );
1074 assert_eq!(r.status(), StatusCode::UNPROCESSABLE_ENTITY);
1075
1076 let r = WebResponseError::<_, DefaultError>::error_response(&ErrorLocked::<_>("err"), &());
1077 assert_eq!(r.status(), StatusCode::LOCKED);
1078
1079 let r = WebResponseError::<_, DefaultError>::error_response(
1080 &ErrorFailedDependency::<_>("err"),
1081 &(),
1082 );
1083 assert_eq!(r.status(), StatusCode::FAILED_DEPENDENCY);
1084
1085 let r = WebResponseError::<_, DefaultError>::error_response(
1086 &ErrorUpgradeRequired::<_>("err"),
1087 &(),
1088 );
1089 assert_eq!(r.status(), StatusCode::UPGRADE_REQUIRED);
1090
1091 let r = WebResponseError::<_, DefaultError>::error_response(
1092 &ErrorPreconditionRequired::<_>("err"),
1093 &(),
1094 );
1095 assert_eq!(r.status(), StatusCode::PRECONDITION_REQUIRED);
1096
1097 let r = WebResponseError::<_, DefaultError>::error_response(
1098 &ErrorTooManyRequests::<_>("err"),
1099 &(),
1100 );
1101 assert_eq!(r.status(), StatusCode::TOO_MANY_REQUESTS);
1102
1103 let r = WebResponseError::<_, DefaultError>::error_response(
1104 &ErrorRequestHeaderFieldsTooLarge::<_>("err"),
1105 &(),
1106 );
1107 assert_eq!(r.status(), StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE);
1108
1109 let r = WebResponseError::<_, DefaultError>::error_response(
1110 &ErrorUnavailableForLegalReasons::<_>("err"),
1111 &(),
1112 );
1113 assert_eq!(r.status(), StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS);
1114
1115 let r = WebResponseError::<_, DefaultError>::error_response(
1116 &ErrorInternalServerError::<_>("err"),
1117 &(),
1118 );
1119 assert_eq!(r.status(), StatusCode::INTERNAL_SERVER_ERROR);
1120
1121 let r = WebResponseError::<_, DefaultError>::error_response(
1122 &ErrorNotImplemented::<_>("err"),
1123 &(),
1124 );
1125 assert_eq!(r.status(), StatusCode::NOT_IMPLEMENTED);
1126
1127 let r =
1128 WebResponseError::<_, DefaultError>::error_response(&ErrorBadGateway::<_>("err"), &());
1129 assert_eq!(r.status(), StatusCode::BAD_GATEWAY);
1130
1131 let r = WebResponseError::<_, DefaultError>::error_response(
1132 &ErrorServiceUnavailable::<_>("err"),
1133 &(),
1134 );
1135 assert_eq!(r.status(), StatusCode::SERVICE_UNAVAILABLE);
1136
1137 let r = WebResponseError::<_, DefaultError>::error_response(
1138 &ErrorGatewayTimeout::<_>("err"),
1139 &(),
1140 );
1141 assert_eq!(r.status(), StatusCode::GATEWAY_TIMEOUT);
1142
1143 let r = WebResponseError::<_, DefaultError>::error_response(
1144 &ErrorHttpVersionNotSupported::<_>("err"),
1145 &(),
1146 );
1147 assert_eq!(r.status(), StatusCode::HTTP_VERSION_NOT_SUPPORTED);
1148
1149 let r = WebResponseError::<_, DefaultError>::error_response(
1150 &ErrorVariantAlsoNegotiates::<_>("err"),
1151 &(),
1152 );
1153 assert_eq!(r.status(), StatusCode::VARIANT_ALSO_NEGOTIATES);
1154
1155 let r = WebResponseError::<_, DefaultError>::error_response(
1156 &ErrorInsufficientStorage::<_>("err"),
1157 &(),
1158 );
1159 assert_eq!(r.status(), StatusCode::INSUFFICIENT_STORAGE);
1160
1161 let r = WebResponseError::<_, DefaultError>::error_response(
1162 &ErrorLoopDetected::<_>("err"),
1163 &(),
1164 );
1165 assert_eq!(r.status(), StatusCode::LOOP_DETECTED);
1166
1167 let r =
1168 WebResponseError::<_, DefaultError>::error_response(&ErrorNotExtended::<_>("err"), &());
1169 assert_eq!(r.status(), StatusCode::NOT_EXTENDED);
1170
1171 let r = WebResponseError::<_, DefaultError>::error_response(
1172 &ErrorNetworkAuthenticationRequired::<_>("err"),
1173 &(),
1174 );
1175 assert_eq!(r.status(), StatusCode::NETWORK_AUTHENTICATION_REQUIRED);
1176 }
1177
1178 #[test]
1179 fn test_default_error_renderers() {
1180 use serde::de::Error as _;
1181
1182 fn status<E: WebResponseError<(), DefaultError>>(err: &E) -> StatusCode {
1183 WebResponseError::<(), DefaultError>::error_response(err, &()).status()
1184 }
1185
1186 let err = serde_json::from_str::<i32>("x").unwrap_err();
1187 assert_eq!(status(&err), StatusCode::INTERNAL_SERVER_ERROR);
1188 let err = serde_urlencoded::to_string(1).unwrap_err();
1189 assert_eq!(status(&err), StatusCode::INTERNAL_SERVER_ERROR);
1190 let err = serde::de::value::Error::custom("bad");
1191 assert_eq!(status(&err), StatusCode::BAD_REQUEST);
1192 assert_eq!(
1193 status(&crate::http::error::Canceled),
1194 StatusCode::INTERNAL_SERVER_ERROR
1195 );
1196 assert_eq!(
1197 status(&BlockingError::<io::Error>::Canceled),
1198 StatusCode::INTERNAL_SERVER_ERROR
1199 );
1200 let err: HttpError = http::header::HeaderName::try_from("bad header")
1201 .unwrap_err()
1202 .into();
1203 assert_eq!(status(&err), StatusCode::INTERNAL_SERVER_ERROR);
1204 assert_eq!(
1205 status(&UrlGenerationError::ResourceNotFound),
1206 StatusCode::INTERNAL_SERVER_ERROR
1207 );
1208 assert_eq!(
1209 status(&crate::client::error::ClientPayloadError(
1210 http::error::PayloadError::Incomplete(None)
1211 )),
1212 StatusCode::BAD_REQUEST
1213 );
1214 assert_eq!(
1215 status(&http::error::PayloadError::Overflow),
1216 StatusCode::PAYLOAD_TOO_LARGE
1217 );
1218
1219 #[cfg(feature = "openssl")]
1220 {
1221 let err = tls_openssl::ssl::Error::from(tls_openssl::error::ErrorStack::get());
1222 assert_eq!(status(&err), StatusCode::BAD_REQUEST);
1223 }
1224 }
1225
1226 #[derive(Debug, thiserror::Error)]
1227 #[error("custom error")]
1228 struct CustomError(#[source] io::Error);
1229
1230 impl WebResponseError<(), DefaultError> for CustomError {}
1231
1232 #[test]
1233 fn test_web_error() {
1234 let err = CustomError(io::Error::other("inner"));
1235 let res = WebResponseError::<(), DefaultError>::error_response(&err, &());
1236 assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
1237
1238 let err = WebError::<(), DefaultError>::from_err(CustomError(io::Error::other("inner")));
1239 assert_eq!(err.source().unwrap().to_string(), "inner");
1240 let res = WebResponseError::error_response(&err, &());
1241 assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
1242
1243 let err = WebError::<(), DefaultError>::from_err(err);
1245 assert_eq!(err.to_string(), "custom error");
1246 let res = WebResponseError::error_response(&err, &());
1247 assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
1248
1249 let err = crate::error::Error::from(crate::http::error::Canceled);
1250 let res = WebResponseError::<(), DefaultError>::error_response(&err, &());
1251 assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
1252 }
1253
1254 #[test]
1255 fn test_internal_error_response_taken() {
1256 let err = InternalError::from_response("err", HttpResponse::Ok().build());
1257 let res = WebResponseError::<(), DefaultError>::error_response(&err, &());
1258 assert_eq!(res.status(), StatusCode::OK);
1259 let res = WebResponseError::<(), DefaultError>::error_response(&err, &());
1260 assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
1261 }
1262}