Skip to main content

ntex/web/
error.rs

1//! Web error
2use std::{cell::RefCell, fmt, io::Write, marker::PhantomData};
3
4pub use ntex_http::error::Error as HttpError;
5pub use serde_json::error::Error as JsonError;
6#[cfg(feature = "url")]
7pub use url_pkg::ParseError as UrlParseError;
8
9use crate::http::body::Body;
10use crate::http::{StatusCode, error, header};
11use crate::util::{BytesMut, Either};
12
13pub use super::error_default::{DefaultError, Error};
14pub use crate::http::error::BlockingError;
15
16use super::{HttpRequest, HttpResponse};
17
18pub trait ErrorRenderer: Sized + 'static {
19    type Container: ErrorContainer;
20}
21
22pub trait ErrorContainer: error::ResponseError + Sized {
23    /// Generate response for error container
24    fn error_response(&self, req: &HttpRequest) -> HttpResponse;
25}
26
27/// Error that can be rendered to a `Response`
28pub trait WebResponseError<Err = DefaultError>:
29    fmt::Display + fmt::Debug + 'static
30where
31    Err: ErrorRenderer,
32{
33    /// Response's status code
34    ///
35    /// Internal server error is generated by default.
36    fn status_code(&self) -> StatusCode {
37        StatusCode::INTERNAL_SERVER_ERROR
38    }
39
40    /// Generate response for error
41    ///
42    /// Internal server error is generated by default.
43    fn error_response(&self, _: &HttpRequest) -> HttpResponse {
44        let mut resp = HttpResponse::new(self.status_code());
45        let mut buf = BytesMut::new();
46        let _ = write!(&mut buf, "{self}");
47        resp.headers_mut().insert(
48            header::CONTENT_TYPE,
49            header::HeaderValue::from_static("text/plain; charset=utf-8"),
50        );
51        resp.set_body(Body::from(buf))
52    }
53}
54
55impl<Err: ErrorRenderer> WebResponseError<Err> for std::convert::Infallible {}
56
57impl<A, B, Err> WebResponseError<Err> for Either<A, B>
58where
59    A: WebResponseError<Err>,
60    B: WebResponseError<Err>,
61    Err: ErrorRenderer,
62{
63    fn status_code(&self) -> StatusCode {
64        match self {
65            Either::Left(a) => a.status_code(),
66            Either::Right(b) => b.status_code(),
67        }
68    }
69
70    fn error_response(&self, req: &HttpRequest) -> HttpResponse {
71        match self {
72            Either::Left(a) => a.error_response(req),
73            Either::Right(b) => b.error_response(req),
74        }
75    }
76}
77
78/// Errors which can occur when attempting to work with `State` extractor
79#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
80pub enum StateExtractorError {
81    #[error("App state is not configured, to configure use App::state()")]
82    NotConfigured,
83}
84
85/// Errors which can occur when attempting to generate resource uri.
86#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
87pub enum UrlGenerationError {
88    /// Resource not found
89    #[error("Resource not found")]
90    ResourceNotFound,
91    /// Not all path pattern covered
92    #[error("Not all path pattern covered")]
93    NotEnoughElements,
94    /// URL parse error
95    #[cfg(feature = "url")]
96    #[error("{0}")]
97    ParseError(
98        #[from]
99        #[source]
100        UrlParseError,
101    ),
102}
103
104/// A set of errors that can occur during parsing urlencoded payloads
105#[derive(Debug, thiserror::Error)]
106pub enum UrlencodedError {
107    /// Cannot decode chunked transfer encoding
108    #[error("Cannot decode chunked transfer encoding")]
109    Chunked,
110    /// Payload size is bigger than allowed. (default: 256kB)
111    #[error(
112        "Urlencoded payload size is bigger ({size} bytes) than allowed (default: {limit} bytes)"
113    )]
114    Overflow { size: usize, limit: usize },
115    /// Payload size is unknown
116    #[error("Payload size is unknown")]
117    UnknownLength,
118    /// Content type error
119    #[error("Content type error")]
120    ContentType,
121    /// Parse error
122    #[error("Parse error")]
123    Parse,
124    /// Payload error
125    #[error("Error that occur during reading payload: {0}")]
126    Payload(
127        #[from]
128        #[source]
129        error::PayloadError,
130    ),
131}
132
133/// A set of errors that can occur during parsing json payloads
134#[derive(Debug, thiserror::Error)]
135pub enum JsonPayloadError {
136    /// Payload size is bigger than allowed. (default: 32kB)
137    #[error("Json payload size is bigger than allowed")]
138    Overflow,
139    /// Content type error
140    #[error("Content type error")]
141    ContentType,
142    /// Deserialize error
143    #[error("Json deserialize error: {0}")]
144    Deserialize(
145        #[from]
146        #[source]
147        serde_json::error::Error,
148    ),
149    /// Payload error
150    #[error("Error that occur during reading payload: {0}")]
151    Payload(
152        #[from]
153        #[source]
154        error::PayloadError,
155    ),
156}
157
158/// A set of errors that can occur during parsing request paths
159#[derive(Debug, thiserror::Error)]
160pub enum PathError {
161    /// Deserialize error
162    #[error("Path deserialize error: {0}")]
163    Deserialize(
164        #[from]
165        #[source]
166        serde::de::value::Error,
167    ),
168}
169
170/// A set of errors that can occur during parsing query strings
171#[derive(Debug, thiserror::Error)]
172pub enum QueryPayloadError {
173    /// Deserialize error
174    #[error("Query deserialize error: {0}")]
175    Deserialize(
176        #[from]
177        #[source]
178        serde::de::value::Error,
179    ),
180}
181
182#[derive(Debug, thiserror::Error)]
183pub enum PayloadError {
184    /// Http error.
185    #[error("{0:?}")]
186    Http(
187        #[from]
188        #[source]
189        error::HttpError,
190    ),
191    #[error("{0}")]
192    Payload(
193        #[from]
194        #[source]
195        error::PayloadError,
196    ),
197    #[error("{0}")]
198    ContentType(
199        #[from]
200        #[source]
201        error::ContentTypeError,
202    ),
203    #[error("Cannot decode body")]
204    Decoding,
205}
206
207/// Helper type that can wrap any error and generate custom response.
208///
209/// In following example any `io::Error` will be converted into "BAD REQUEST"
210/// response as opposite to *INTERNAL SERVER ERROR* which is defined by
211/// default.
212///
213/// ```rust
214/// use ntex::http::Request;
215///
216/// fn index(req: Request) -> Result<&'static str, std::io::Error> {
217///     Err(std::io::Error::new(std::io::ErrorKind::Other, "error"))
218/// }
219/// ```
220pub struct InternalError<T, Err = DefaultError> {
221    cause: T,
222    status: InternalErrorType,
223    _t: PhantomData<Err>,
224}
225
226enum InternalErrorType {
227    Status(StatusCode),
228    Response(RefCell<Option<HttpResponse>>),
229}
230
231impl<T> InternalError<T> {
232    /// Create `InternalError` instance
233    pub fn default(cause: T, status: StatusCode) -> Self {
234        InternalError {
235            cause,
236            status: InternalErrorType::Status(status),
237            _t: PhantomData,
238        }
239    }
240}
241
242impl<T, Err> InternalError<T, Err> {
243    /// Create `InternalError` instance
244    pub fn new(cause: T, status: StatusCode) -> Self {
245        InternalError {
246            cause,
247            status: InternalErrorType::Status(status),
248            _t: PhantomData,
249        }
250    }
251
252    /// Create `InternalError` with predefined `Response`.
253    pub fn from_response(cause: T, response: HttpResponse) -> Self {
254        InternalError {
255            cause,
256            status: InternalErrorType::Response(RefCell::new(Some(response))),
257            _t: PhantomData,
258        }
259    }
260}
261
262impl<T, E> fmt::Debug for InternalError<T, E>
263where
264    T: fmt::Debug + 'static,
265{
266    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267        write!(f, "web::InternalError({:?})", &self.cause)
268    }
269}
270
271impl<T, E> fmt::Display for InternalError<T, E>
272where
273    T: fmt::Display + 'static,
274{
275    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276        fmt::Display::fmt(&self.cause, f)
277    }
278}
279
280impl<T: fmt::Display + fmt::Debug + 'static, E> std::error::Error for InternalError<T, E> {}
281
282impl<T, E> WebResponseError<E> for InternalError<T, E>
283where
284    T: fmt::Debug + fmt::Display + 'static,
285    E: ErrorRenderer,
286{
287    fn error_response(&self, _: &HttpRequest) -> HttpResponse {
288        crate::http::error::ResponseError::error_response(self)
289    }
290}
291
292impl<T, E> crate::http::error::ResponseError for InternalError<T, E>
293where
294    T: fmt::Debug + fmt::Display + 'static,
295    E: ErrorRenderer,
296{
297    fn error_response(&self) -> HttpResponse {
298        match self.status {
299            InternalErrorType::Status(st) => {
300                let mut res = HttpResponse::new(st);
301                let mut buf = BytesMut::new();
302                let _ = write!(&mut buf, "{self}");
303                res.headers_mut().insert(
304                    header::CONTENT_TYPE,
305                    header::HeaderValue::from_static("text/plain; charset=utf-8"),
306                );
307                res.set_body(Body::from(buf))
308            }
309            InternalErrorType::Response(ref resp) => {
310                if let Some(resp) = resp.borrow_mut().take() {
311                    resp
312                } else {
313                    HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
314                }
315            }
316        }
317    }
318}
319
320/// Helper function that creates wrapper of any error and generate *BAD
321/// REQUEST* response.
322#[allow(non_snake_case)]
323pub fn ErrorBadRequest<T, E>(err: T) -> InternalError<T, E>
324where
325    T: fmt::Debug + fmt::Display + 'static,
326{
327    InternalError::new(err, StatusCode::BAD_REQUEST)
328}
329
330/// Helper function that creates wrapper of any error and generate
331/// *UNAUTHORIZED* response.
332#[allow(non_snake_case)]
333pub fn ErrorUnauthorized<T, E>(err: T) -> InternalError<T, E>
334where
335    T: fmt::Debug + fmt::Display + 'static,
336{
337    InternalError::new(err, StatusCode::UNAUTHORIZED)
338}
339
340/// Helper function that creates wrapper of any error and generate
341/// *`PAYMENT_REQUIRED`* response.
342#[allow(non_snake_case)]
343pub fn ErrorPaymentRequired<T, E>(err: T) -> InternalError<T, E>
344where
345    T: fmt::Debug + fmt::Display + 'static,
346{
347    InternalError::new(err, StatusCode::PAYMENT_REQUIRED)
348}
349
350/// Helper function that creates wrapper of any error and generate *FORBIDDEN*
351/// response.
352#[allow(non_snake_case)]
353pub fn ErrorForbidden<T, E>(err: T) -> InternalError<T, E>
354where
355    T: fmt::Debug + fmt::Display + 'static,
356{
357    InternalError::new(err, StatusCode::FORBIDDEN)
358}
359
360/// Helper function that creates wrapper of any error and generate *NOT FOUND*
361/// response.
362#[allow(non_snake_case)]
363pub fn ErrorNotFound<T, E>(err: T) -> InternalError<T, E>
364where
365    T: fmt::Debug + fmt::Display + 'static,
366{
367    InternalError::new(err, StatusCode::NOT_FOUND)
368}
369
370/// Helper function that creates wrapper of any error and generate *METHOD NOT
371/// ALLOWED* response.
372#[allow(non_snake_case)]
373pub fn ErrorMethodNotAllowed<T, E>(err: T) -> InternalError<T, E>
374where
375    T: fmt::Debug + fmt::Display + 'static,
376{
377    InternalError::new(err, StatusCode::METHOD_NOT_ALLOWED)
378}
379
380/// Helper function that creates wrapper of any error and generate *NOT
381/// ACCEPTABLE* response.
382#[allow(non_snake_case)]
383pub fn ErrorNotAcceptable<T, E>(err: T) -> InternalError<T, E>
384where
385    T: fmt::Debug + fmt::Display + 'static,
386{
387    InternalError::new(err, StatusCode::NOT_ACCEPTABLE)
388}
389
390/// Helper function that creates wrapper of any error and generate *PROXY
391/// AUTHENTICATION REQUIRED* response.
392#[allow(non_snake_case)]
393pub fn ErrorProxyAuthenticationRequired<T, E>(err: T) -> InternalError<T, E>
394where
395    T: fmt::Debug + fmt::Display + 'static,
396{
397    InternalError::new(err, StatusCode::PROXY_AUTHENTICATION_REQUIRED)
398}
399
400/// Helper function that creates wrapper of any error and generate *REQUEST
401/// TIMEOUT* response.
402#[allow(non_snake_case)]
403pub fn ErrorRequestTimeout<T, E>(err: T) -> InternalError<T, E>
404where
405    T: fmt::Debug + fmt::Display + 'static,
406{
407    InternalError::new(err, StatusCode::REQUEST_TIMEOUT)
408}
409
410/// Helper function that creates wrapper of any error and generate *CONFLICT*
411/// response.
412#[allow(non_snake_case)]
413pub fn ErrorConflict<T, E>(err: T) -> InternalError<T, E>
414where
415    T: fmt::Debug + fmt::Display + 'static,
416{
417    InternalError::new(err, StatusCode::CONFLICT)
418}
419
420/// Helper function that creates wrapper of any error and generate *GONE*
421/// response.
422#[allow(non_snake_case)]
423pub fn ErrorGone<T, E>(err: T) -> InternalError<T, E>
424where
425    T: fmt::Debug + fmt::Display + 'static,
426{
427    InternalError::new(err, StatusCode::GONE)
428}
429
430/// Helper function that creates wrapper of any error and generate *LENGTH
431/// REQUIRED* response.
432#[allow(non_snake_case)]
433pub fn ErrorLengthRequired<T, E>(err: T) -> InternalError<T, E>
434where
435    T: fmt::Debug + fmt::Display + 'static,
436{
437    InternalError::new(err, StatusCode::LENGTH_REQUIRED)
438}
439
440/// Helper function that creates wrapper of any error and generate
441/// *PAYLOAD TOO LARGE* response.
442#[allow(non_snake_case)]
443pub fn ErrorPayloadTooLarge<T, E>(err: T) -> InternalError<T, E>
444where
445    T: fmt::Debug + fmt::Display + 'static,
446{
447    InternalError::new(err, StatusCode::PAYLOAD_TOO_LARGE)
448}
449
450/// Helper function that creates wrapper of any error and generate
451/// *URI TOO LONG* response.
452#[allow(non_snake_case)]
453pub fn ErrorUriTooLong<T, E>(err: T) -> InternalError<T, E>
454where
455    T: fmt::Debug + fmt::Display + 'static,
456{
457    InternalError::new(err, StatusCode::URI_TOO_LONG)
458}
459
460/// Helper function that creates wrapper of any error and generate
461/// *UNSUPPORTED MEDIA TYPE* response.
462#[allow(non_snake_case)]
463pub fn ErrorUnsupportedMediaType<T, E>(err: T) -> InternalError<T, E>
464where
465    T: fmt::Debug + fmt::Display + 'static,
466{
467    InternalError::new(err, StatusCode::UNSUPPORTED_MEDIA_TYPE)
468}
469
470/// Helper function that creates wrapper of any error and generate
471/// *RANGE NOT SATISFIABLE* response.
472#[allow(non_snake_case)]
473pub fn ErrorRangeNotSatisfiable<T, E>(err: T) -> InternalError<T, E>
474where
475    T: fmt::Debug + fmt::Display + 'static,
476{
477    InternalError::new(err, StatusCode::RANGE_NOT_SATISFIABLE)
478}
479
480/// Helper function that creates wrapper of any error and generate
481/// *IM A TEAPOT* response.
482#[allow(non_snake_case)]
483pub fn ErrorImATeapot<T, E>(err: T) -> InternalError<T, E>
484where
485    T: fmt::Debug + fmt::Display + 'static,
486{
487    InternalError::new(err, StatusCode::IM_A_TEAPOT)
488}
489
490/// Helper function that creates wrapper of any error and generate
491/// *MISDIRECTED REQUEST* response.
492#[allow(non_snake_case)]
493pub fn ErrorMisdirectedRequest<T, E>(err: T) -> InternalError<T, E>
494where
495    T: fmt::Debug + fmt::Display + 'static,
496{
497    InternalError::new(err, StatusCode::MISDIRECTED_REQUEST)
498}
499
500/// Helper function that creates wrapper of any error and generate
501/// *UNPROCESSABLE ENTITY* response.
502#[allow(non_snake_case)]
503pub fn ErrorUnprocessableEntity<T, E>(err: T) -> InternalError<T, E>
504where
505    T: fmt::Debug + fmt::Display + 'static,
506{
507    InternalError::new(err, StatusCode::UNPROCESSABLE_ENTITY)
508}
509
510/// Helper function that creates wrapper of any error and generate
511/// *LOCKED* response.
512#[allow(non_snake_case)]
513pub fn ErrorLocked<T, E>(err: T) -> InternalError<T, E>
514where
515    T: fmt::Debug + fmt::Display + 'static,
516{
517    InternalError::new(err, StatusCode::LOCKED)
518}
519
520/// Helper function that creates wrapper of any error and generate
521/// *FAILED DEPENDENCY* response.
522#[allow(non_snake_case)]
523pub fn ErrorFailedDependency<T, E>(err: T) -> InternalError<T, E>
524where
525    T: fmt::Debug + fmt::Display + 'static,
526{
527    InternalError::new(err, StatusCode::FAILED_DEPENDENCY)
528}
529
530/// Helper function that creates wrapper of any error and generate
531/// *UPGRADE REQUIRED* response.
532#[allow(non_snake_case)]
533pub fn ErrorUpgradeRequired<T, E>(err: T) -> InternalError<T, E>
534where
535    T: fmt::Debug + fmt::Display + 'static,
536{
537    InternalError::new(err, StatusCode::UPGRADE_REQUIRED)
538}
539
540/// Helper function that creates wrapper of any error and generate
541/// *PRECONDITION FAILED* response.
542#[allow(non_snake_case)]
543pub fn ErrorPreconditionFailed<T, E>(err: T) -> InternalError<T, E>
544where
545    T: fmt::Debug + fmt::Display + 'static,
546{
547    InternalError::new(err, StatusCode::PRECONDITION_FAILED)
548}
549
550/// Helper function that creates wrapper of any error and generate
551/// *PRECONDITION REQUIRED* response.
552#[allow(non_snake_case)]
553pub fn ErrorPreconditionRequired<T, E>(err: T) -> InternalError<T, E>
554where
555    T: fmt::Debug + fmt::Display + 'static,
556{
557    InternalError::new(err, StatusCode::PRECONDITION_REQUIRED)
558}
559
560/// Helper function that creates wrapper of any error and generate
561/// *TOO MANY REQUESTS* response.
562#[allow(non_snake_case)]
563pub fn ErrorTooManyRequests<T, E>(err: T) -> InternalError<T, E>
564where
565    T: fmt::Debug + fmt::Display + 'static,
566{
567    InternalError::new(err, StatusCode::TOO_MANY_REQUESTS)
568}
569
570/// Helper function that creates wrapper of any error and generate
571/// *REQUEST HEADER FIELDS TOO LARGE* response.
572#[allow(non_snake_case)]
573pub fn ErrorRequestHeaderFieldsTooLarge<T, E>(err: T) -> InternalError<T, E>
574where
575    T: fmt::Debug + fmt::Display + 'static,
576{
577    InternalError::new(err, StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE)
578}
579
580/// Helper function that creates wrapper of any error and generate
581/// *UNAVAILABLE FOR LEGAL REASONS* response.
582#[allow(non_snake_case)]
583pub fn ErrorUnavailableForLegalReasons<T, E>(err: T) -> InternalError<T, E>
584where
585    T: fmt::Debug + fmt::Display + 'static,
586{
587    InternalError::new(err, StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS)
588}
589
590/// Helper function that creates wrapper of any error and generate
591/// *EXPECTATION FAILED* response.
592#[allow(non_snake_case)]
593pub fn ErrorExpectationFailed<T, E>(err: T) -> InternalError<T, E>
594where
595    T: fmt::Debug + fmt::Display + 'static,
596{
597    InternalError::new(err, StatusCode::EXPECTATION_FAILED)
598}
599
600/// Helper function that creates wrapper of any error and
601/// generate *INTERNAL SERVER ERROR* response.
602#[allow(non_snake_case)]
603pub fn ErrorInternalServerError<T, E>(err: T) -> InternalError<T, E>
604where
605    T: fmt::Debug + fmt::Display + 'static,
606{
607    InternalError::new(err, StatusCode::INTERNAL_SERVER_ERROR)
608}
609
610/// Helper function that creates wrapper of any error and
611/// generate *NOT IMPLEMENTED* response.
612#[allow(non_snake_case)]
613pub fn ErrorNotImplemented<T, E>(err: T) -> InternalError<T, E>
614where
615    T: fmt::Debug + fmt::Display + 'static,
616{
617    InternalError::new(err, StatusCode::NOT_IMPLEMENTED)
618}
619
620/// Helper function that creates wrapper of any error and
621/// generate *BAD GATEWAY* response.
622#[allow(non_snake_case)]
623pub fn ErrorBadGateway<T, E>(err: T) -> InternalError<T, E>
624where
625    T: fmt::Debug + fmt::Display + 'static,
626{
627    InternalError::new(err, StatusCode::BAD_GATEWAY)
628}
629
630/// Helper function that creates wrapper of any error and
631/// generate *SERVICE UNAVAILABLE* response.
632#[allow(non_snake_case)]
633pub fn ErrorServiceUnavailable<T, E>(err: T) -> InternalError<T, E>
634where
635    T: fmt::Debug + fmt::Display + 'static,
636{
637    InternalError::new(err, StatusCode::SERVICE_UNAVAILABLE)
638}
639
640/// Helper function that creates wrapper of any error and
641/// generate *GATEWAY TIMEOUT* response.
642#[allow(non_snake_case)]
643pub fn ErrorGatewayTimeout<T, E>(err: T) -> InternalError<T, E>
644where
645    T: fmt::Debug + fmt::Display + 'static,
646{
647    InternalError::new(err, StatusCode::GATEWAY_TIMEOUT)
648}
649
650/// Helper function that creates wrapper of any error and
651/// generate *HTTP VERSION NOT SUPPORTED* response.
652#[allow(non_snake_case)]
653pub fn ErrorHttpVersionNotSupported<T, E>(err: T) -> InternalError<T, E>
654where
655    T: fmt::Debug + fmt::Display + 'static,
656{
657    InternalError::new(err, StatusCode::HTTP_VERSION_NOT_SUPPORTED)
658}
659
660/// Helper function that creates wrapper of any error and
661/// generate *VARIANT ALSO NEGOTIATES* response.
662#[allow(non_snake_case)]
663pub fn ErrorVariantAlsoNegotiates<T, E>(err: T) -> InternalError<T, E>
664where
665    T: fmt::Debug + fmt::Display + 'static,
666{
667    InternalError::new(err, StatusCode::VARIANT_ALSO_NEGOTIATES)
668}
669
670/// Helper function that creates wrapper of any error and
671/// generate *INSUFFICIENT STORAGE* response.
672#[allow(non_snake_case)]
673pub fn ErrorInsufficientStorage<T, E>(err: T) -> InternalError<T, E>
674where
675    T: fmt::Debug + fmt::Display + 'static,
676{
677    InternalError::new(err, StatusCode::INSUFFICIENT_STORAGE)
678}
679
680/// Helper function that creates wrapper of any error and
681/// generate *LOOP DETECTED* response.
682#[allow(non_snake_case)]
683pub fn ErrorLoopDetected<T, E>(err: T) -> InternalError<T, E>
684where
685    T: fmt::Debug + fmt::Display + 'static,
686{
687    InternalError::new(err, StatusCode::LOOP_DETECTED)
688}
689
690/// Helper function that creates wrapper of any error and
691/// generate *NOT EXTENDED* response.
692#[allow(non_snake_case)]
693pub fn ErrorNotExtended<T, E>(err: T) -> InternalError<T, E>
694where
695    T: fmt::Debug + fmt::Display + 'static,
696{
697    InternalError::new(err, StatusCode::NOT_EXTENDED)
698}
699
700/// Helper function that creates wrapper of any error and
701/// generate *NETWORK AUTHENTICATION REQUIRED* response.
702#[allow(non_snake_case)]
703pub fn ErrorNetworkAuthenticationRequired<T, E>(err: T) -> InternalError<T, E>
704where
705    T: fmt::Debug + fmt::Display + 'static,
706{
707    InternalError::new(err, StatusCode::NETWORK_AUTHENTICATION_REQUIRED)
708}
709
710#[cfg(test)]
711mod tests {
712    use std::io;
713
714    use super::*;
715    use crate::client::error::{ClientError, ConnectError};
716    use crate::{http, web::test::TestRequest};
717
718    #[test]
719    fn test_into_error() {
720        let err = UrlencodedError::UnknownLength;
721        let e: Error = err.into();
722        let s = format!("{e}");
723        assert!(s.contains("Payload size is unknown"));
724
725        let e = Error::new(UrlencodedError::UnknownLength);
726        let s = format!("{e:?}");
727        assert!(s.contains("UnknownLength"));
728
729        let res = crate::http::ResponseError::error_response(&e);
730        assert_eq!(res.status(), StatusCode::LENGTH_REQUIRED);
731        assert_eq!(
732            e.as_response_error().status_code(),
733            StatusCode::LENGTH_REQUIRED
734        );
735    }
736
737    #[test]
738    fn test_other_errors() {
739        use crate::util::timeout::TimeoutError;
740
741        let req = TestRequest::default().to_http_request();
742        let resp =
743            Error::from(TimeoutError::<UrlencodedError>::Timeout).error_response(&req);
744        assert_eq!(resp.status(), StatusCode::GATEWAY_TIMEOUT);
745
746        let resp = Error::from(TimeoutError::<UrlencodedError>::Service(
747            UrlencodedError::Chunked,
748        ))
749        .error_response(&req);
750        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
751
752        let resp = WebResponseError::<DefaultError>::error_response(
753            &ClientError::Connect(ConnectError::Timeout),
754            &req,
755        );
756        assert_eq!(resp.status(), StatusCode::GATEWAY_TIMEOUT);
757
758        let resp = WebResponseError::<DefaultError>::error_response(
759            &ClientError::Connect(ConnectError::SslIsNotSupported),
760            &req,
761        );
762        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
763
764        let resp = WebResponseError::<DefaultError>::error_response(
765            &ClientError::TunnelNotSupported,
766            &req,
767        );
768        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
769
770        #[cfg(feature = "cookie")]
771        {
772            let resp: HttpResponse = WebResponseError::<DefaultError>::error_response(
773                &coo_kie::ParseError::EmptyName,
774                &req,
775            );
776            assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
777        }
778
779        let resp = WebResponseError::<DefaultError>::error_response(
780            &crate::http::error::ContentTypeError::ParseError,
781            &req,
782        );
783        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
784
785        let err = serde_urlencoded::from_str::<i32>("bad query").unwrap_err();
786        let resp = WebResponseError::<DefaultError>::error_response(&err, &req);
787        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
788
789        let err = PayloadError::Decoding;
790        let resp = WebResponseError::<DefaultError>::error_response(&err, &req);
791        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
792
793        #[allow(invalid_from_utf8)]
794        let err = std::str::from_utf8(b"\xF0").unwrap_err();
795        let resp = WebResponseError::<DefaultError>::error_response(&err, &req);
796        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
797
798        let err = http::error::PayloadError::EncodingCorrupted;
799        let resp = WebResponseError::<DefaultError>::error_response(&err, &req);
800        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
801    }
802
803    #[test]
804    fn test_either_error() {
805        let req = TestRequest::default().to_http_request();
806
807        let err: Either<ClientError, PayloadError> =
808            Either::Left(ClientError::TunnelNotSupported);
809        let code = WebResponseError::<DefaultError>::status_code(&err);
810        assert_eq!(code, StatusCode::INTERNAL_SERVER_ERROR);
811        let resp = WebResponseError::<DefaultError>::error_response(&err, &req);
812        assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
813
814        let err: Either<ClientError, PayloadError> = Either::Right(PayloadError::Decoding);
815        let code = WebResponseError::<DefaultError>::status_code(&err);
816        assert_eq!(code, StatusCode::BAD_REQUEST);
817        let resp = WebResponseError::<DefaultError>::error_response(&err, &req);
818        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
819    }
820
821    #[test]
822    fn test_io_error() {
823        assert_eq!(
824            StatusCode::NOT_FOUND,
825            WebResponseError::<DefaultError>::status_code(&io::Error::new(
826                io::ErrorKind::NotFound,
827                ""
828            )),
829        );
830        assert_eq!(
831            StatusCode::FORBIDDEN,
832            WebResponseError::<DefaultError>::status_code(&io::Error::new(
833                io::ErrorKind::PermissionDenied,
834                ""
835            )),
836        );
837        assert_eq!(
838            StatusCode::INTERNAL_SERVER_ERROR,
839            WebResponseError::<DefaultError>::status_code(&io::Error::other("")),
840        );
841    }
842
843    #[test]
844    fn test_urlencoded_error() {
845        let req = TestRequest::default().to_http_request();
846        let resp: HttpResponse = WebResponseError::<DefaultError>::error_response(
847            &UrlencodedError::Overflow { size: 0, limit: 0 },
848            &req,
849        );
850        assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
851        let resp: HttpResponse = WebResponseError::<DefaultError>::error_response(
852            &UrlencodedError::UnknownLength,
853            &req,
854        );
855        assert_eq!(resp.status(), StatusCode::LENGTH_REQUIRED);
856        let resp: HttpResponse = WebResponseError::<DefaultError>::error_response(
857            &UrlencodedError::ContentType,
858            &req,
859        );
860        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
861    }
862
863    #[test]
864    fn test_json_payload_error() {
865        let req = TestRequest::default().to_http_request();
866        let resp: HttpResponse = WebResponseError::<DefaultError>::error_response(
867            &JsonPayloadError::Overflow,
868            &req,
869        );
870        assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
871        let resp: HttpResponse = WebResponseError::<DefaultError>::error_response(
872            &JsonPayloadError::ContentType,
873            &req,
874        );
875        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
876    }
877
878    #[test]
879    fn test_query_payload_error() {
880        let req = TestRequest::default().to_http_request();
881
882        let err = QueryPayloadError::Deserialize(
883            serde_urlencoded::from_str::<i32>("bad query").unwrap_err(),
884        );
885
886        let resp: HttpResponse =
887            WebResponseError::<DefaultError>::error_response(&err, &req);
888        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
889        assert_eq!(
890            WebResponseError::<DefaultError>::status_code(&err),
891            StatusCode::BAD_REQUEST
892        );
893    }
894
895    #[test]
896    fn test_path_error() {
897        let req = TestRequest::default().to_http_request();
898        let err = PathError::Deserialize(
899            serde_urlencoded::from_str::<i32>("bad path").unwrap_err(),
900        );
901        let resp: HttpResponse =
902            WebResponseError::<DefaultError>::error_response(&err, &req);
903        assert_eq!(resp.status(), StatusCode::NOT_FOUND);
904        assert_eq!(
905            WebResponseError::<DefaultError>::status_code(&err),
906            StatusCode::NOT_FOUND
907        );
908    }
909
910    #[test]
911    fn test_handshake_error() {
912        use crate::ws::error::HandshakeError;
913
914        let req = TestRequest::default().to_http_request();
915
916        let resp = HandshakeError::GetMethodRequired.error_response(&req);
917        assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
918        let resp = HandshakeError::NoWebsocketUpgrade.error_response(&req);
919        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
920        let resp = HandshakeError::NoConnectionUpgrade.error_response(&req);
921        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
922        let resp = HandshakeError::NoVersionHeader.error_response(&req);
923        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
924        let resp = HandshakeError::UnsupportedVersion.error_response(&req);
925        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
926        let resp = HandshakeError::BadWebsocketKey.error_response(&req);
927        assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
928    }
929
930    #[test]
931    fn test_error_helpers() {
932        let err = ErrorBadRequest::<_, DefaultError>("err");
933        assert!(format!("{err:?}").contains("web::InternalError"));
934
935        let err: InternalError<_, DefaultError> =
936            InternalError::from_response("err", HttpResponse::BadRequest().finish());
937        let r: HttpResponse = err.into();
938        assert_eq!(r.status(), StatusCode::BAD_REQUEST);
939
940        let r: HttpResponse = ErrorBadRequest::<_, DefaultError>("err").into();
941        assert_eq!(r.status(), StatusCode::BAD_REQUEST);
942
943        let r: HttpResponse = ErrorUnauthorized::<_, DefaultError>("err").into();
944        assert_eq!(r.status(), StatusCode::UNAUTHORIZED);
945
946        let r: HttpResponse = ErrorPaymentRequired::<_, DefaultError>("err").into();
947        assert_eq!(r.status(), StatusCode::PAYMENT_REQUIRED);
948
949        let r: HttpResponse = ErrorForbidden::<_, DefaultError>("err").into();
950        assert_eq!(r.status(), StatusCode::FORBIDDEN);
951
952        let r: HttpResponse = ErrorNotFound::<_, DefaultError>("err").into();
953        assert_eq!(r.status(), StatusCode::NOT_FOUND);
954
955        let r: HttpResponse = ErrorMethodNotAllowed::<_, DefaultError>("err").into();
956        assert_eq!(r.status(), StatusCode::METHOD_NOT_ALLOWED);
957
958        let r: HttpResponse = ErrorNotAcceptable::<_, DefaultError>("err").into();
959        assert_eq!(r.status(), StatusCode::NOT_ACCEPTABLE);
960
961        let r: HttpResponse =
962            ErrorProxyAuthenticationRequired::<_, DefaultError>("err").into();
963        assert_eq!(r.status(), StatusCode::PROXY_AUTHENTICATION_REQUIRED);
964
965        let r: HttpResponse = ErrorRequestTimeout::<_, DefaultError>("err").into();
966        assert_eq!(r.status(), StatusCode::REQUEST_TIMEOUT);
967
968        let r: HttpResponse = ErrorConflict::<_, DefaultError>("err").into();
969        assert_eq!(r.status(), StatusCode::CONFLICT);
970
971        let r: HttpResponse = ErrorGone::<_, DefaultError>("err").into();
972        assert_eq!(r.status(), StatusCode::GONE);
973
974        let r: HttpResponse = ErrorLengthRequired::<_, DefaultError>("err").into();
975        assert_eq!(r.status(), StatusCode::LENGTH_REQUIRED);
976
977        let r: HttpResponse = ErrorPreconditionFailed::<_, DefaultError>("err").into();
978        assert_eq!(r.status(), StatusCode::PRECONDITION_FAILED);
979
980        let r: HttpResponse = ErrorPayloadTooLarge::<_, DefaultError>("err").into();
981        assert_eq!(r.status(), StatusCode::PAYLOAD_TOO_LARGE);
982
983        let r: HttpResponse = ErrorUriTooLong::<_, DefaultError>("err").into();
984        assert_eq!(r.status(), StatusCode::URI_TOO_LONG);
985
986        let r: HttpResponse = ErrorUnsupportedMediaType::<_, DefaultError>("err").into();
987        assert_eq!(r.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE);
988
989        let r: HttpResponse = ErrorRangeNotSatisfiable::<_, DefaultError>("err").into();
990        assert_eq!(r.status(), StatusCode::RANGE_NOT_SATISFIABLE);
991
992        let r: HttpResponse = ErrorExpectationFailed::<_, DefaultError>("err").into();
993        assert_eq!(r.status(), StatusCode::EXPECTATION_FAILED);
994
995        let r: HttpResponse = ErrorImATeapot::<_, DefaultError>("err").into();
996        assert_eq!(r.status(), StatusCode::IM_A_TEAPOT);
997
998        let r: HttpResponse = ErrorMisdirectedRequest::<_, DefaultError>("err").into();
999        assert_eq!(r.status(), StatusCode::MISDIRECTED_REQUEST);
1000
1001        let r: HttpResponse = ErrorUnprocessableEntity::<_, DefaultError>("err").into();
1002        assert_eq!(r.status(), StatusCode::UNPROCESSABLE_ENTITY);
1003
1004        let r: HttpResponse = ErrorLocked::<_, DefaultError>("err").into();
1005        assert_eq!(r.status(), StatusCode::LOCKED);
1006
1007        let r: HttpResponse = ErrorFailedDependency::<_, DefaultError>("err").into();
1008        assert_eq!(r.status(), StatusCode::FAILED_DEPENDENCY);
1009
1010        let r: HttpResponse = ErrorUpgradeRequired::<_, DefaultError>("err").into();
1011        assert_eq!(r.status(), StatusCode::UPGRADE_REQUIRED);
1012
1013        let r: HttpResponse = ErrorPreconditionRequired::<_, DefaultError>("err").into();
1014        assert_eq!(r.status(), StatusCode::PRECONDITION_REQUIRED);
1015
1016        let r: HttpResponse = ErrorTooManyRequests::<_, DefaultError>("err").into();
1017        assert_eq!(r.status(), StatusCode::TOO_MANY_REQUESTS);
1018
1019        let r: HttpResponse =
1020            ErrorRequestHeaderFieldsTooLarge::<_, DefaultError>("err").into();
1021        assert_eq!(r.status(), StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE);
1022
1023        let r: HttpResponse =
1024            ErrorUnavailableForLegalReasons::<_, DefaultError>("err").into();
1025        assert_eq!(r.status(), StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS);
1026
1027        let r: HttpResponse = ErrorInternalServerError::<_, DefaultError>("err").into();
1028        assert_eq!(r.status(), StatusCode::INTERNAL_SERVER_ERROR);
1029
1030        let r: HttpResponse = ErrorNotImplemented::<_, DefaultError>("err").into();
1031        assert_eq!(r.status(), StatusCode::NOT_IMPLEMENTED);
1032
1033        let r: HttpResponse = ErrorBadGateway::<_, DefaultError>("err").into();
1034        assert_eq!(r.status(), StatusCode::BAD_GATEWAY);
1035
1036        let r: HttpResponse = ErrorServiceUnavailable::<_, DefaultError>("err").into();
1037        assert_eq!(r.status(), StatusCode::SERVICE_UNAVAILABLE);
1038
1039        let r: HttpResponse = ErrorGatewayTimeout::<_, DefaultError>("err").into();
1040        assert_eq!(r.status(), StatusCode::GATEWAY_TIMEOUT);
1041
1042        let r: HttpResponse = ErrorHttpVersionNotSupported::<_, DefaultError>("err").into();
1043        assert_eq!(r.status(), StatusCode::HTTP_VERSION_NOT_SUPPORTED);
1044
1045        let r: HttpResponse = ErrorVariantAlsoNegotiates::<_, DefaultError>("err").into();
1046        assert_eq!(r.status(), StatusCode::VARIANT_ALSO_NEGOTIATES);
1047
1048        let r: HttpResponse = ErrorInsufficientStorage::<_, DefaultError>("err").into();
1049        assert_eq!(r.status(), StatusCode::INSUFFICIENT_STORAGE);
1050
1051        let r: HttpResponse = ErrorLoopDetected::<_, DefaultError>("err").into();
1052        assert_eq!(r.status(), StatusCode::LOOP_DETECTED);
1053
1054        let r: HttpResponse = ErrorNotExtended::<_, DefaultError>("err").into();
1055        assert_eq!(r.status(), StatusCode::NOT_EXTENDED);
1056
1057        let r: HttpResponse =
1058            ErrorNetworkAuthenticationRequired::<_, DefaultError>("err").into();
1059        assert_eq!(r.status(), StatusCode::NETWORK_AUTHENTICATION_REQUIRED);
1060    }
1061}