use actix_web as aweb; use aweb::error::{JsonPayloadError, QueryPayloadError}; use meilisearch_types::error::{Code, ErrorCode, ResponseError}; #[derive(Debug, thiserror::Error)] pub enum MeilisearchHttpError { #[error("A Content-Type header is missing. Accepted values for the Content-Type header are: {}", .0.iter().map(|s| format!("`{}`", s)).collect::>().join(", "))] MissingContentType(Vec), #[error( "The Content-Type `{0}` is invalid. Accepted values for the Content-Type header are: {}", .1.iter().map(|s| format!("`{}`", s)).collect::>().join(", ") )] InvalidContentType(String, Vec), } impl ErrorCode for MeilisearchHttpError { fn error_code(&self) -> Code { match self { MeilisearchHttpError::MissingContentType(_) => Code::MissingContentType, MeilisearchHttpError::InvalidContentType(_, _) => Code::InvalidContentType, } } } impl From for aweb::Error { fn from(other: MeilisearchHttpError) -> Self { aweb::Error::from(ResponseError::from(other)) } } #[derive(Debug, thiserror::Error)] pub enum PayloadError { #[error("{0}")] Json(JsonPayloadError), #[error("{0}")] Query(QueryPayloadError), #[error("The json payload provided is malformed. `{0}`.")] MalformedPayload(serde_json::error::Error), #[error("A json payload is missing.")] MissingPayload, } impl ErrorCode for PayloadError { fn error_code(&self) -> Code { match self { PayloadError::Json(err) => match err { JsonPayloadError::Overflow { .. } => Code::PayloadTooLarge, JsonPayloadError::ContentType => Code::UnsupportedMediaType, JsonPayloadError::Payload(aweb::error::PayloadError::Overflow) => { Code::PayloadTooLarge } JsonPayloadError::Payload(_) => Code::BadRequest, JsonPayloadError::Deserialize(_) => Code::BadRequest, JsonPayloadError::Serialize(_) => Code::Internal, _ => Code::Internal, }, PayloadError::Query(err) => match err { QueryPayloadError::Deserialize(_) => Code::BadRequest, _ => Code::Internal, }, PayloadError::MissingPayload => Code::MissingPayload, PayloadError::MalformedPayload(_) => Code::MalformedPayload, } } } impl From for PayloadError { fn from(other: JsonPayloadError) -> Self { match other { JsonPayloadError::Deserialize(e) if e.classify() == serde_json::error::Category::Eof && e.line() == 1 && e.column() == 0 => { Self::MissingPayload } JsonPayloadError::Deserialize(e) if e.classify() != serde_json::error::Category::Data => { Self::MalformedPayload(e) } _ => Self::Json(other), } } } impl From for PayloadError { fn from(other: QueryPayloadError) -> Self { Self::Query(other) } } impl From for aweb::Error { fn from(other: PayloadError) -> Self { aweb::Error::from(ResponseError::from(other)) } }