2020-05-22 12:03:57 +02:00
use std ::error ;
2020-05-27 12:04:35 +02:00
use std ::fmt ;
2020-04-10 19:05:05 +02:00
2020-04-08 14:13:45 +02:00
use actix_http ::ResponseBuilder ;
2020-04-10 19:05:05 +02:00
use actix_web as aweb ;
2020-06-03 18:21:03 +02:00
use actix_web ::error ::{ JsonPayloadError , QueryPayloadError } ;
2020-04-07 17:47:35 +02:00
use actix_web ::http ::StatusCode ;
2020-10-12 10:57:19 +02:00
use serde ::ser ::{ Serialize , Serializer , SerializeStruct } ;
2019-10-31 15:00:36 +01:00
2020-05-22 12:03:57 +02:00
use meilisearch_error ::{ ErrorCode , Code } ;
#[ derive(Debug) ]
pub struct ResponseError {
inner : Box < dyn ErrorCode > ,
}
2020-05-27 10:20:54 +02:00
impl error ::Error for ResponseError { }
impl ErrorCode for ResponseError {
fn error_code ( & self ) -> Code {
self . inner . error_code ( )
}
}
2020-05-22 12:03:57 +02:00
impl fmt ::Display for ResponseError {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
self . inner . fmt ( f )
}
}
impl From < Error > for ResponseError {
fn from ( error : Error ) -> ResponseError {
ResponseError { inner : Box ::new ( error ) }
}
}
2020-10-22 15:29:39 +02:00
impl From < meilisearch_core ::Error > for ResponseError {
fn from ( err : meilisearch_core ::Error ) -> ResponseError {
ResponseError { inner : Box ::new ( err ) }
}
}
impl From < meilisearch_schema ::Error > for ResponseError {
fn from ( err : meilisearch_schema ::Error ) -> ResponseError {
ResponseError { inner : Box ::new ( err ) }
}
}
impl From < FacetCountError > for ResponseError {
fn from ( err : FacetCountError ) -> ResponseError {
ResponseError { inner : Box ::new ( err ) }
}
}
impl Serialize for ResponseError {
fn serialize < S > ( & self , serializer : S ) -> Result < S ::Ok , S ::Error >
where
S : Serializer ,
{
let struct_name = " ResponseError " ;
let field_count = 4 ;
let mut state = serializer . serialize_struct ( struct_name , field_count ) ? ;
state . serialize_field ( " message " , & self . to_string ( ) ) ? ;
state . serialize_field ( " errorCode " , & self . error_name ( ) ) ? ;
state . serialize_field ( " errorType " , & self . error_type ( ) ) ? ;
state . serialize_field ( " errorLink " , & self . error_url ( ) ) ? ;
state . end ( )
}
}
impl aweb ::error ::ResponseError for ResponseError {
fn error_response ( & self ) -> aweb ::HttpResponse {
ResponseBuilder ::new ( self . status_code ( ) ) . json ( & self )
}
fn status_code ( & self ) -> StatusCode {
self . http_status ( )
}
}
2020-04-07 17:47:35 +02:00
#[ derive(Debug) ]
2020-05-19 18:20:29 +02:00
pub enum Error {
2019-10-31 15:00:36 +01:00
BadParameter ( String , String ) ,
2020-04-17 14:52:13 +02:00
BadRequest ( String ) ,
2019-10-31 15:00:36 +01:00
CreateIndex ( String ) ,
2020-04-17 14:52:13 +02:00
DocumentNotFound ( String ) ,
IndexNotFound ( String ) ,
2020-07-28 14:41:49 +02:00
IndexAlreadyExists ( String ) ,
2020-04-17 14:52:13 +02:00
Internal ( String ) ,
2020-03-05 11:44:30 +01:00
InvalidIndexUid ,
2020-04-17 14:52:13 +02:00
InvalidToken ( String ) ,
MissingAuthorizationHeader ,
NotFound ( String ) ,
OpenIndex ( String ) ,
2020-05-19 13:53:31 +02:00
RetrieveDocument ( u32 , String ) ,
2020-04-17 14:52:13 +02:00
SearchDocuments ( String ) ,
2020-05-07 12:29:18 +02:00
PayloadTooLarge ,
UnsupportedMediaType ,
2020-09-29 12:18:09 +02:00
DumpAlreadyInProgress ,
2020-10-12 10:57:19 +02:00
DumpProcessFailed ( String ) ,
2020-05-12 14:26:43 +02:00
}
2020-05-22 12:03:57 +02:00
impl error ::Error for Error { }
impl ErrorCode for Error {
fn error_code ( & self ) -> Code {
2020-05-22 18:04:23 +02:00
use Error ::* ;
match self {
BadParameter ( _ , _ ) = > Code ::BadParameter ,
BadRequest ( _ ) = > Code ::BadRequest ,
CreateIndex ( _ ) = > Code ::CreateIndex ,
DocumentNotFound ( _ ) = > Code ::DocumentNotFound ,
IndexNotFound ( _ ) = > Code ::IndexNotFound ,
2020-07-28 14:41:49 +02:00
IndexAlreadyExists ( _ ) = > Code ::IndexAlreadyExists ,
2020-05-22 18:04:23 +02:00
Internal ( _ ) = > Code ::Internal ,
InvalidIndexUid = > Code ::InvalidIndexUid ,
InvalidToken ( _ ) = > Code ::InvalidToken ,
MissingAuthorizationHeader = > Code ::MissingAuthorizationHeader ,
NotFound ( _ ) = > Code ::NotFound ,
OpenIndex ( _ ) = > Code ::OpenIndex ,
RetrieveDocument ( _ , _ ) = > Code ::RetrieveDocument ,
SearchDocuments ( _ ) = > Code ::SearchDocuments ,
PayloadTooLarge = > Code ::PayloadTooLarge ,
UnsupportedMediaType = > Code ::UnsupportedMediaType ,
2020-09-29 12:18:09 +02:00
DumpAlreadyInProgress = > Code ::DumpAlreadyInProgress ,
2020-10-12 10:57:19 +02:00
DumpProcessFailed ( _ ) = > Code ::DumpProcessFailed ,
2020-05-22 18:04:23 +02:00
}
2020-05-22 12:03:57 +02:00
}
}
#[ derive(Debug) ]
2020-05-12 14:26:43 +02:00
pub enum FacetCountError {
AttributeNotSet ( String ) ,
SyntaxError ( String ) ,
UnexpectedToken { found : String , expected : & 'static [ & 'static str ] } ,
NoFacetSet ,
}
2020-05-22 12:03:57 +02:00
impl error ::Error for FacetCountError { }
impl ErrorCode for FacetCountError {
fn error_code ( & self ) -> Code {
2020-05-22 18:04:23 +02:00
Code ::BadRequest
2020-05-22 12:03:57 +02:00
}
}
2020-05-12 14:26:43 +02:00
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 {
2020-08-13 17:01:20 +02:00
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 " ) ,
2020-05-12 14:26:43 +02:00
}
}
2020-04-17 14:52:13 +02:00
}
2020-05-19 18:20:29 +02:00
impl Error {
pub fn internal ( err : impl fmt ::Display ) -> Error {
Error ::Internal ( err . to_string ( ) )
2020-04-17 14:52:13 +02:00
}
2020-05-19 18:20:29 +02:00
pub fn bad_request ( err : impl fmt ::Display ) -> Error {
Error ::BadRequest ( err . to_string ( ) )
2020-04-17 14:52:13 +02:00
}
2020-05-19 18:20:29 +02:00
pub fn missing_authorization_header ( ) -> Error {
Error ::MissingAuthorizationHeader
2020-04-17 14:52:13 +02:00
}
2020-05-19 18:20:29 +02:00
pub fn invalid_token ( err : impl fmt ::Display ) -> Error {
Error ::InvalidToken ( err . to_string ( ) )
2020-04-17 14:52:13 +02:00
}
2020-05-19 18:20:29 +02:00
pub fn not_found ( err : impl fmt ::Display ) -> Error {
Error ::NotFound ( err . to_string ( ) )
2020-04-17 14:52:13 +02:00
}
2020-05-19 18:20:29 +02:00
pub fn index_not_found ( err : impl fmt ::Display ) -> Error {
Error ::IndexNotFound ( err . to_string ( ) )
2020-04-17 14:52:13 +02:00
}
2020-05-19 18:20:29 +02:00
pub fn document_not_found ( err : impl fmt ::Display ) -> Error {
Error ::DocumentNotFound ( err . to_string ( ) )
2020-04-17 14:52:13 +02:00
}
2020-05-19 18:20:29 +02:00
pub fn bad_parameter ( param : impl fmt ::Display , err : impl fmt ::Display ) -> Error {
Error ::BadParameter ( param . to_string ( ) , err . to_string ( ) )
2020-04-17 14:52:13 +02:00
}
2020-05-19 18:20:29 +02:00
pub fn open_index ( err : impl fmt ::Display ) -> Error {
Error ::OpenIndex ( err . to_string ( ) )
2020-04-17 14:52:13 +02:00
}
2020-05-19 18:20:29 +02:00
pub fn create_index ( err : impl fmt ::Display ) -> Error {
Error ::CreateIndex ( err . to_string ( ) )
2020-04-17 14:52:13 +02:00
}
2020-05-19 18:20:29 +02:00
pub fn invalid_index_uid ( ) -> Error {
Error ::InvalidIndexUid
2020-04-17 14:52:13 +02:00
}
2020-05-22 18:04:23 +02:00
pub fn retrieve_document ( doc_id : u32 , err : impl fmt ::Display ) -> Error {
2020-05-19 18:20:29 +02:00
Error ::RetrieveDocument ( doc_id , err . to_string ( ) )
2020-04-17 14:52:13 +02:00
}
2020-05-19 18:20:29 +02:00
pub fn search_documents ( err : impl fmt ::Display ) -> Error {
Error ::SearchDocuments ( err . to_string ( ) )
2020-04-17 14:52:13 +02:00
}
2020-07-28 14:41:49 +02:00
2020-09-29 12:18:09 +02:00
pub fn dump_conflict ( ) -> Error {
Error ::DumpAlreadyInProgress
2020-07-28 14:41:49 +02:00
}
2020-10-12 10:57:19 +02:00
pub fn dump_failed ( message : String ) -> Error {
Error ::DumpProcessFailed ( message )
2020-07-28 14:41:49 +02:00
}
2019-10-31 15:00:36 +01:00
}
2020-05-19 18:20:29 +02:00
impl fmt ::Display for Error {
2020-04-07 17:47:35 +02:00
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
match self {
2020-04-17 14:52:13 +02:00
Self ::BadParameter ( param , err ) = > write! ( f , " Url parameter {} error: {} " , param , err ) ,
2020-04-24 15:00:52 +02:00
Self ::BadRequest ( err ) = > f . write_str ( err ) ,
2020-04-17 14:52:13 +02:00
Self ::CreateIndex ( err ) = > write! ( f , " Impossible to create index; {} " , err ) ,
2020-04-07 17:47:35 +02:00
Self ::DocumentNotFound ( document_id ) = > write! ( f , " Document with id {} not found " , document_id ) ,
2020-04-17 14:52:13 +02:00
Self ::IndexNotFound ( index_uid ) = > write! ( f , " Index {} not found " , index_uid ) ,
2020-07-28 14:41:49 +02:00
Self ::IndexAlreadyExists ( index_uid ) = > write! ( f , " Index {} already exists " , index_uid ) ,
2020-04-24 15:00:52 +02:00
Self ::Internal ( err ) = > f . write_str ( err ) ,
2020-04-17 14:52:13 +02:00
Self ::InvalidIndexUid = > f . write_str ( " Index must have a valid uid; Index uid can be of type integer or string only composed of alphanumeric characters, hyphens (-) and underscores (_). " ) ,
Self ::InvalidToken ( err ) = > write! ( f , " Invalid API key: {} " , err ) ,
Self ::MissingAuthorizationHeader = > f . write_str ( " You must have an authorization token " ) ,
Self ::NotFound ( err ) = > write! ( f , " {} not found " , err ) ,
2020-04-07 17:47:35 +02:00
Self ::OpenIndex ( err ) = > write! ( f , " Impossible to open index; {} " , err ) ,
2020-08-13 17:01:20 +02:00
Self ::RetrieveDocument ( id , err ) = > write! ( f , " Impossible to retrieve the document with id: {}; {} " , id , err ) ,
Self ::SearchDocuments ( err ) = > write! ( f , " Impossible to search documents; {} " , err ) ,
Self ::PayloadTooLarge = > f . write_str ( " Payload too large " ) ,
2020-05-12 15:23:35 +02:00
Self ::UnsupportedMediaType = > f . write_str ( " Unsupported media type " ) ,
2020-09-29 12:18:09 +02:00
Self ::DumpAlreadyInProgress = > f . write_str ( " Another dump is already in progress " ) ,
2020-10-12 10:57:19 +02:00
Self ::DumpProcessFailed ( message ) = > write! ( f , " Dump process failed: {} " , message ) ,
2020-04-07 17:47:35 +02:00
}
2019-10-31 15:00:36 +01:00
}
}
2020-07-28 14:41:49 +02:00
impl From < std ::io ::Error > for Error {
fn from ( err : std ::io ::Error ) -> Error {
Error ::Internal ( err . to_string ( ) )
}
}
2020-05-19 18:20:29 +02:00
impl From < actix_http ::Error > for Error {
fn from ( err : actix_http ::Error ) -> Error {
Error ::Internal ( err . to_string ( ) )
2020-07-02 16:20:45 +02:00
}
}
2020-07-28 14:41:49 +02:00
impl From < meilisearch_core ::Error > for Error {
fn from ( err : meilisearch_core ::Error ) -> Error {
2020-07-02 16:20:45 +02:00
Error ::Internal ( err . to_string ( ) )
}
}
2020-07-28 14:41:49 +02:00
impl From < serde_json ::error ::Error > for Error {
fn from ( err : serde_json ::error ::Error ) -> Error {
2020-07-02 16:20:45 +02:00
Error ::Internal ( err . to_string ( ) )
2020-04-17 14:52:13 +02:00
}
}
2020-05-07 12:29:18 +02:00
2020-05-19 18:20:29 +02:00
impl From < JsonPayloadError > for Error {
fn from ( err : JsonPayloadError ) -> Error {
2020-05-07 12:29:18 +02:00
match err {
2020-05-19 18:20:29 +02:00
JsonPayloadError ::Deserialize ( err ) = > Error ::BadRequest ( format! ( " Invalid JSON: {} " , err ) ) ,
JsonPayloadError ::Overflow = > Error ::PayloadTooLarge ,
JsonPayloadError ::ContentType = > Error ::UnsupportedMediaType ,
JsonPayloadError ::Payload ( err ) = > Error ::BadRequest ( format! ( " Problem while decoding the request: {} " , err ) ) ,
2020-05-12 14:26:43 +02:00
}
2020-05-07 12:29:18 +02:00
}
}
2020-06-03 18:21:03 +02:00
impl From < QueryPayloadError > for Error {
fn from ( err : QueryPayloadError ) -> Error {
match err {
QueryPayloadError ::Deserialize ( err ) = > Error ::BadRequest ( format! ( " Invalid query parameters: {} " , err ) ) ,
}
}
}
pub fn payload_error_handler < E : Into < Error > > ( err : E ) -> ResponseError {
let error : Error = err . into ( ) ;
2020-05-22 12:03:57 +02:00
error . into ( )
2020-05-07 12:29:18 +02:00
}