2021-06-15 03:26:35 +08:00
use std ::error ::Error ;
2020-12-12 20:32:06 +08:00
use std ::fmt ;
use actix_web as aweb ;
2021-04-21 19:49:21 +08:00
use actix_web ::body ::Body ;
2020-12-12 20:32:06 +08:00
use actix_web ::http ::StatusCode ;
2021-09-08 18:34:56 +08:00
use actix_web ::HttpResponseBuilder ;
2021-06-22 01:20:04 +08:00
use aweb ::error ::{ JsonPayloadError , QueryPayloadError } ;
2021-03-16 01:11:10 +08:00
use meilisearch_error ::{ Code , ErrorCode } ;
2021-06-22 01:20:04 +08:00
use serde ::{ Deserialize , Serialize } ;
2021-06-15 03:26:35 +08:00
2021-09-30 16:26:30 +08:00
#[ derive(Debug, thiserror::Error) ]
pub enum MeilisearchHttpError {
#[ error( " A Content-Type header is missing. Accepted values for the Content-Type header are: \" application/json \" , \" application/x-ndjson \" , \" test/csv \" " ) ]
MissingContentType ,
2021-09-30 17:17:42 +08:00
#[ error( " The Content-Type \" {0} \" is invalid. Accepted values for the Content-Type header are: \" application/json \" , \" application/x-ndjson \" , \" test/csv \" " ) ]
InvalidContentType ( String ) ,
2021-09-30 16:26:30 +08:00
}
impl ErrorCode for MeilisearchHttpError {
fn error_code ( & self ) -> Code {
match self {
MeilisearchHttpError ::MissingContentType = > Code ::MissingContentType ,
2021-09-30 17:17:42 +08:00
MeilisearchHttpError ::InvalidContentType ( _ ) = > Code ::InvalidContentType ,
2021-09-30 16:26:30 +08:00
}
}
}
2021-06-22 00:42:47 +08:00
#[ derive(Debug, Serialize, Deserialize, Clone) ]
#[ serde(rename_all = " camelCase " ) ]
2020-12-12 20:32:06 +08:00
pub struct ResponseError {
2021-06-22 00:42:47 +08:00
#[ serde(skip) ]
code : StatusCode ,
message : String ,
error_code : String ,
error_type : String ,
error_link : String ,
2020-12-12 20:32:06 +08:00
}
impl fmt ::Display for ResponseError {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
2021-06-22 00:42:47 +08:00
self . message . fmt ( f )
2020-12-12 20:32:06 +08:00
}
}
2021-06-22 00:42:47 +08:00
impl < T > From < T > for ResponseError
2021-06-22 01:20:04 +08:00
where
T : ErrorCode ,
2021-06-22 00:42:47 +08:00
{
fn from ( other : T ) -> Self {
Self {
code : other . http_status ( ) ,
message : other . to_string ( ) ,
error_code : other . error_name ( ) ,
error_type : other . error_type ( ) ,
error_link : other . error_url ( ) ,
}
2020-12-12 20:32:06 +08:00
}
}
impl aweb ::error ::ResponseError for ResponseError {
2021-09-08 18:34:56 +08:00
fn error_response ( & self ) -> aweb ::HttpResponse < Body > {
2021-04-21 19:49:21 +08:00
let json = serde_json ::to_vec ( self ) . unwrap ( ) ;
2021-09-08 18:34:56 +08:00
HttpResponseBuilder ::new ( self . status_code ( ) )
2021-06-22 00:48:05 +08:00
. content_type ( " application/json " )
. body ( json )
2020-12-12 20:32:06 +08:00
}
fn status_code ( & self ) -> StatusCode {
2021-06-22 00:42:47 +08:00
self . code
2020-12-12 20:32:06 +08:00
}
}
2021-06-22 01:20:04 +08:00
impl fmt ::Display for PayloadError {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
match self {
PayloadError ::Json ( e ) = > e . fmt ( f ) ,
PayloadError ::Query ( e ) = > e . fmt ( f ) ,
}
}
}
#[ derive(Debug) ]
pub enum PayloadError {
Json ( JsonPayloadError ) ,
Query ( QueryPayloadError ) ,
}
impl Error for PayloadError { }
impl ErrorCode for PayloadError {
fn error_code ( & self ) -> Code {
match self {
PayloadError ::Json ( err ) = > match err {
2021-09-08 18:34:56 +08:00
JsonPayloadError ::Overflow { .. } = > Code ::PayloadTooLarge ,
2021-06-22 01:20:04 +08:00
JsonPayloadError ::ContentType = > Code ::UnsupportedMediaType ,
2021-06-23 20:48:33 +08:00
JsonPayloadError ::Payload ( aweb ::error ::PayloadError ::Overflow ) = > {
Code ::PayloadTooLarge
}
JsonPayloadError ::Deserialize ( _ ) | JsonPayloadError ::Payload ( _ ) = > Code ::BadRequest ,
2021-06-22 01:20:04 +08:00
JsonPayloadError ::Serialize ( _ ) = > Code ::Internal ,
_ = > Code ::Internal ,
} ,
PayloadError ::Query ( err ) = > match err {
QueryPayloadError ::Deserialize ( _ ) = > Code ::BadRequest ,
_ = > Code ::Internal ,
} ,
}
}
}
impl From < JsonPayloadError > for PayloadError {
fn from ( other : JsonPayloadError ) -> Self {
Self ::Json ( other )
}
}
impl From < QueryPayloadError > for PayloadError {
fn from ( other : QueryPayloadError ) -> Self {
Self ::Query ( other )
}
}
2021-06-22 00:42:47 +08:00
pub fn payload_error_handler < E > ( err : E ) -> ResponseError
where
2021-06-22 01:20:04 +08:00
E : Into < PayloadError > ,
2021-06-22 00:42:47 +08:00
{
2021-06-22 01:20:04 +08:00
err . into ( ) . into ( )
2021-06-22 00:42:47 +08:00
}