error handling

This commit is contained in:
mpostma 2020-05-12 14:26:43 +02:00
parent 869b6019c6
commit 5051a796a0
2 changed files with 55 additions and 15 deletions

View File

@ -27,6 +27,40 @@ pub enum ResponseError {
PayloadTooLarge, PayloadTooLarge,
UnsupportedMediaType, UnsupportedMediaType,
FacetExpression(String), FacetExpression(String),
FacetCount(String),
}
pub enum FacetCountError {
AttributeNotSet(String),
SyntaxError(String),
UnexpectedToken { found: String, expected: &'static [&'static str] },
NoFacetSet,
}
impl FacetCountError {
pub fn unexpected_token(found: impl ToString, expected: &'static [&'static str]) -> FacetCountError {
let found = found.to_string();
FacetCountError::UnexpectedToken { expected, found }
}
}
impl From<serde_json::error::Error> for FacetCountError {
fn from(other: serde_json::error::Error) -> FacetCountError {
FacetCountError::SyntaxError(other.to_string())
}
}
impl fmt::Display for FacetCountError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use FacetCountError::*;
match self {
AttributeNotSet(attr) => write!(f, "attribute {} is not set as facet", attr),
SyntaxError(msg) => write!(f, "syntax error: {}", msg),
UnexpectedToken { expected, found } => write!(f, "unexpected {} found, expected {:?}", found, expected),
NoFacetSet => write!(f, "can't perform facet count, as no facet is set"),
}
}
} }
impl ResponseError { impl ResponseError {
@ -113,6 +147,7 @@ impl fmt::Display for ResponseError {
Self::FacetExpression(e) => write!(f, "error parsing facet filter expression: {}", e), Self::FacetExpression(e) => write!(f, "error parsing facet filter expression: {}", e),
Self::PayloadTooLarge => f.write_str("Payload to large"), Self::PayloadTooLarge => f.write_str("Payload to large"),
Self::UnsupportedMediaType => f.write_str("Unsupported media type") Self::UnsupportedMediaType => f.write_str("Unsupported media type")
Self::FacetCount(e) => write!(f, "error with facet count: {}", e),
} }
} }
} }
@ -134,6 +169,7 @@ impl aweb::error::ResponseError for ResponseError {
| Self::RetrieveDocument(_, _) | Self::RetrieveDocument(_, _)
| Self::FacetExpression(_) | Self::FacetExpression(_)
| Self::SearchDocuments(_) | Self::SearchDocuments(_)
| Self::FacetCount(_)
| Self::FilterParsing(_) => StatusCode::BAD_REQUEST, | Self::FilterParsing(_) => StatusCode::BAD_REQUEST,
Self::DocumentNotFound(_) Self::DocumentNotFound(_)
| Self::IndexNotFound(_) | Self::IndexNotFound(_)
@ -198,18 +234,23 @@ impl From<actix_http::Error> for ResponseError {
} }
} }
impl From<JsonPayloadError> for ResponseError { impl From<FacetCountError> for ResponseError {
fn from(err: JsonPayloadError) -> ResponseError { fn from(other: FacetCountError) -> ResponseError {
match err { ResponseError::FacetCount(other.to_string())
JsonPayloadError::Deserialize(err) => ResponseError::BadRequest(format!("Invalid JSON: {}", err)),
JsonPayloadError::Overflow => ResponseError::PayloadTooLarge,
JsonPayloadError::ContentType => ResponseError::UnsupportedMediaType,
JsonPayloadError::Payload(err) => ResponseError::BadRequest(format!("Problem while decoding the request: {}", err)),
}
} }
} }
impl From<JsonPayloadError> for ResponseError {
fn from(err: JsonPayloadError) -> ResponseError {
match err {
JsonPayloadError::Deserialize(err) => ResponseError::BadRequest(format!("Invalid JSON: {}", err)),
JsonPayloadError::Overflow => ResponseError::PayloadTooLarge,
JsonPayloadError::ContentType => ResponseError::UnsupportedMediaType,
JsonPayloadError::Payload(err) => ResponseError::BadRequest(format!("Problem while decoding the request: {}", err)),
}
}
}
pub fn json_error_handler(err: JsonPayloadError) -> ResponseError { pub fn json_error_handler(err: JsonPayloadError) -> ResponseError {
err.into() err.into()
} }

View File

@ -7,7 +7,7 @@ use actix_web_macros::get;
use serde::Deserialize; use serde::Deserialize;
use serde_json::Value; use serde_json::Value;
use crate::error::ResponseError; use crate::error::{ResponseError, FacetCountError};
use crate::helpers::meilisearch::IndexSearchExt; use crate::helpers::meilisearch::IndexSearchExt;
use crate::helpers::Authentication; use crate::helpers::Authentication;
use crate::routes::IndexParam; use crate::routes::IndexParam;
@ -100,9 +100,8 @@ async fn search_with_url_query(
let field_ids = prepare_facet_list(&facets, &schema, attrs)?; let field_ids = prepare_facet_list(&facets, &schema, attrs)?;
search_builder.add_facets(field_ids); search_builder.add_facets(field_ids);
}, },
None => return Err(ResponseError::FacetExpression("can't return facets count, as no facet is set".to_string())) None => return Err(FacetCountError::NoFacetSet.into())
} }
} }
if let Some(attributes_to_crop) = &params.attributes_to_crop { if let Some(attributes_to_crop) = &params.attributes_to_crop {
@ -188,16 +187,16 @@ fn prepare_facet_list(facets: &str, schema: &Schema, facet_attrs: &[FieldId]) ->
Value::String(facet) => { Value::String(facet) => {
if let Some(id) = schema.id(&facet) { if let Some(id) = schema.id(&facet) {
if !facet_attrs.contains(&id) { if !facet_attrs.contains(&id) {
return Err(ResponseError::FacetExpression("Only attributes set as facet can be counted".to_string())); // TODO make special error return Err(FacetCountError::AttributeNotSet(facet));
} }
field_ids.push((id, facet)); field_ids.push((id, facet));
} }
} }
bad_val => return Err(ResponseError::FacetExpression(format!("expected String found {}", bad_val))) bad_val => return Err(FacetCountError::unexpected_token(bad_val, &["String"])),
} }
} }
Ok(field_ids) Ok(field_ids)
} }
bad_val => return Err(ResponseError::FacetExpression(format!("expected Array found {}", bad_val))) bad_val => return Err(FacetCountError::unexpected_token(bad_val, &["[String]"]))
} }
} }