foxtive_ntex_multipart/
result.rs1use crate::file_validator::InputError;
2use foxtive::StatusCode;
3use foxtive::helpers::time::current_timestamp;
4use ntex::web::{HttpRequest, HttpResponse, WebResponseError};
5use serde_json::json;
6use std::fmt::{Display, Formatter};
7use std::io::Error;
8use thiserror::Error;
9
10pub type MultipartResult<T> = Result<T, MultipartError>;
11
12#[derive(Debug, Error)]
13pub enum MultipartError {
14 NoFile,
15 IoError(Error),
16 NoContentType(String),
17 ParseError(String),
18 MissingDataField(String),
19 InvalidContentDisposition(String),
20 NtexError(ntex_multipart::MultipartError),
21 ValidationError(InputError),
22}
23
24impl From<Error> for MultipartError {
25 fn from(value: Error) -> Self {
26 MultipartError::IoError(value)
27 }
28}
29
30impl WebResponseError for MultipartError {
31 fn status_code(&self) -> StatusCode {
32 match self {
33 MultipartError::IoError(_) => StatusCode::INTERNAL_SERVER_ERROR,
34 MultipartError::NoFile
35 | MultipartError::NoContentType(_)
36 | MultipartError::ParseError(_)
37 | MultipartError::MissingDataField(_)
38 | MultipartError::InvalidContentDisposition(_)
39 | MultipartError::NtexError(_)
40 | MultipartError::ValidationError(_) => StatusCode::BAD_REQUEST,
41 }
42 }
43
44 fn error_response(&self, _: &HttpRequest) -> HttpResponse {
45 match self {
46 MultipartError::NoFile => send_response(self.status_code(), "No file(s) were uploaded"),
47 MultipartError::IoError(_) => {
48 send_response(self.status_code(), "Internal Server Error")
49 }
50 MultipartError::NoContentType(err) => send_response(self.status_code(), err),
51 MultipartError::ParseError(err) => send_response(self.status_code(), err),
52 MultipartError::MissingDataField(err) => send_response(self.status_code(), err),
53 MultipartError::InvalidContentDisposition(err) => {
54 send_response(self.status_code(), err)
55 }
56 MultipartError::NtexError(err) => send_response(self.status_code(), &err.to_string()),
57 MultipartError::ValidationError(err) => {
58 send_response(self.status_code(), &err.error.to_string())
59 }
60 }
61 }
62}
63
64fn send_response(status_code: StatusCode, message: &str) -> HttpResponse {
65 let data: Option<String> = None;
66 let code = match status_code {
67 StatusCode::BAD_REQUEST => "004",
68 _ => "010",
69 };
70
71 HttpResponse::build(status_code).json(&json!({
72 "success": false,
73 "message": message,
74 "code": code,
75 "timestamp": current_timestamp(),
76 "data": data
77 }))
78}
79impl Display for MultipartError {
80 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
81 match self {
82 MultipartError::IoError(err) => {
83 write!(f, "{err}")
84 }
85 MultipartError::NoFile => {
86 write!(f, "No file was uploaded")
87 }
88 MultipartError::MissingDataField(ct) => {
89 write!(f, "Data field '{ct}' is required")
90 }
91 MultipartError::NoContentType(ct) => {
92 write!(f, "Invalid content type: {ct}")
93 }
94 MultipartError::ParseError(pe) => {
95 write!(f, "Failed to parse post data: {pe}")
96 }
97 MultipartError::InvalidContentDisposition(err) => {
98 write!(f, "Invalid content disposition: {err}")
99 }
100 MultipartError::NtexError(err) => {
101 write!(f, "{err}")
102 }
103 MultipartError::ValidationError(err) => write!(f, "{}", err.error),
104 }
105 }
106}