2020-05-20 00:13:02 +08:00
|
|
|
use std::fmt;
|
2020-05-27 16:20:54 +08:00
|
|
|
|
2020-05-20 00:13:02 +08:00
|
|
|
use actix_http::http::StatusCode;
|
|
|
|
|
|
|
|
pub trait ErrorCode: std::error::Error {
|
|
|
|
fn error_code(&self) -> Code;
|
2020-05-27 16:20:54 +08:00
|
|
|
|
|
|
|
/// returns the HTTP status code ascociated with the error
|
|
|
|
fn http_status(&self) -> StatusCode {
|
|
|
|
self.error_code().http()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// returns the doc url ascociated with the error
|
|
|
|
fn error_url(&self) -> String {
|
|
|
|
self.error_code().url()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// returns error name, used as error code
|
|
|
|
fn error_name(&self) -> String {
|
|
|
|
self.error_code().name()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// return the error type
|
|
|
|
fn error_type(&self) -> String {
|
|
|
|
self.error_code().r#type()
|
|
|
|
}
|
2020-05-20 00:13:02 +08:00
|
|
|
}
|
|
|
|
|
2020-05-26 01:11:38 +08:00
|
|
|
enum ErrorType {
|
|
|
|
InternalError,
|
|
|
|
InvalidRequest,
|
|
|
|
Authentication,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for ErrorType {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
use ErrorType::*;
|
|
|
|
|
|
|
|
match self {
|
|
|
|
InternalError => write!(f, "internal_error"),
|
|
|
|
InvalidRequest => write!(f, "invalid_request"),
|
|
|
|
Authentication => write!(f, "authentication"),
|
|
|
|
}
|
|
|
|
}
|
2020-05-20 00:13:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub enum Code {
|
2020-05-26 17:32:03 +08:00
|
|
|
// index related error
|
|
|
|
CreateIndex,
|
|
|
|
IndexAlreadyExists,
|
|
|
|
IndexNotFound,
|
|
|
|
InvalidIndexUid,
|
|
|
|
OpenIndex,
|
|
|
|
|
|
|
|
// invalid state error
|
|
|
|
InvalidState,
|
|
|
|
MissingPrimaryKey,
|
2020-05-26 18:17:53 +08:00
|
|
|
PrimaryKeyAlreadyPresent,
|
2020-05-26 17:32:03 +08:00
|
|
|
|
|
|
|
MaxFieldsLimitExceeded,
|
2020-05-27 18:04:35 +08:00
|
|
|
MissingDocumentId,
|
2020-05-26 17:32:03 +08:00
|
|
|
|
|
|
|
Facet,
|
2020-05-27 18:04:35 +08:00
|
|
|
Filter,
|
2020-05-26 17:32:03 +08:00
|
|
|
|
2020-05-23 00:04:23 +08:00
|
|
|
BadParameter,
|
|
|
|
BadRequest,
|
|
|
|
DocumentNotFound,
|
|
|
|
Internal,
|
|
|
|
InvalidToken,
|
|
|
|
Maintenance,
|
|
|
|
MissingAuthorizationHeader,
|
|
|
|
MissingHeader,
|
|
|
|
NotFound,
|
2020-05-27 18:04:35 +08:00
|
|
|
PayloadTooLarge,
|
2020-05-23 00:04:23 +08:00
|
|
|
RetrieveDocument,
|
|
|
|
SearchDocuments,
|
|
|
|
UnsupportedMediaType,
|
2020-05-20 00:13:02 +08:00
|
|
|
Other,
|
|
|
|
}
|
|
|
|
|
2020-05-23 00:04:23 +08:00
|
|
|
impl Code {
|
|
|
|
|
|
|
|
/// ascociate a `Code` variant to the actual ErrCode
|
|
|
|
fn err_code(&self) -> ErrCode {
|
|
|
|
use Code::*;
|
|
|
|
|
|
|
|
match self {
|
2020-05-26 17:32:03 +08:00
|
|
|
// index related errors
|
2020-05-26 01:11:38 +08:00
|
|
|
CreateIndex => ErrCode::invalid("create_index", StatusCode::BAD_REQUEST),
|
2020-05-26 17:32:03 +08:00
|
|
|
IndexAlreadyExists => ErrCode::invalid("existing_index", StatusCode::BAD_REQUEST),
|
2020-05-27 18:04:35 +08:00
|
|
|
IndexNotFound => ErrCode::invalid("index_not_found", StatusCode::NOT_FOUND), InvalidIndexUid => ErrCode::invalid("invalid_index_uid", StatusCode::BAD_REQUEST),
|
2020-05-26 17:32:03 +08:00
|
|
|
OpenIndex => ErrCode::internal("open_index", StatusCode::INTERNAL_SERVER_ERROR),
|
|
|
|
|
|
|
|
// invalid state error
|
|
|
|
InvalidState => ErrCode::internal("invalid_state", StatusCode::INTERNAL_SERVER_ERROR),
|
|
|
|
// FIXME probably not an internal statuscode there
|
2020-05-26 18:17:53 +08:00
|
|
|
MissingPrimaryKey => ErrCode::internal("missing_primary_key", StatusCode::INTERNAL_SERVER_ERROR),
|
|
|
|
PrimaryKeyAlreadyPresent => ErrCode::internal("primary_key_already_present", StatusCode::INTERNAL_SERVER_ERROR),
|
2020-05-26 17:32:03 +08:00
|
|
|
|
|
|
|
// invalid document
|
|
|
|
MaxFieldsLimitExceeded => ErrCode::invalid("max_field_limit_exceeded", StatusCode::BAD_REQUEST),
|
2020-05-27 18:04:35 +08:00
|
|
|
MissingDocumentId => ErrCode::invalid("missing_document_id", StatusCode::BAD_REQUEST),
|
2020-05-26 17:32:03 +08:00
|
|
|
|
2020-05-27 18:04:35 +08:00
|
|
|
Facet => ErrCode::invalid("invalid_facet", StatusCode::BAD_REQUEST),
|
|
|
|
Filter => ErrCode::invalid("invalid_filter", StatusCode::BAD_REQUEST),
|
2020-05-26 17:32:03 +08:00
|
|
|
|
|
|
|
BadParameter => ErrCode::invalid("bad_parameter", StatusCode::BAD_REQUEST),
|
|
|
|
BadRequest => ErrCode::invalid("bad_request", StatusCode::BAD_REQUEST),
|
2020-05-27 18:04:35 +08:00
|
|
|
DocumentNotFound => ErrCode::internal("document_not_found", StatusCode::NOT_FOUND),
|
|
|
|
Internal => ErrCode::internal("internal", StatusCode::INTERNAL_SERVER_ERROR),
|
2020-05-26 19:41:34 +08:00
|
|
|
InvalidToken => ErrCode::authentication("invalid_token", StatusCode::UNAUTHORIZED),
|
2020-05-27 18:04:35 +08:00
|
|
|
Maintenance => ErrCode::internal("maintenance", StatusCode::SERVICE_UNAVAILABLE),
|
2020-05-26 19:41:34 +08:00
|
|
|
MissingAuthorizationHeader => ErrCode::authentication("missing_authorization_header", StatusCode::FORBIDDEN),
|
2020-05-27 18:04:35 +08:00
|
|
|
MissingHeader => ErrCode::authentication("missing_header", StatusCode::UNAUTHORIZED),
|
|
|
|
NotFound => ErrCode::invalid("not_found", StatusCode::NOT_FOUND),
|
2020-05-26 19:41:34 +08:00
|
|
|
PayloadTooLarge => ErrCode::invalid("payload_too_large", StatusCode::PAYLOAD_TOO_LARGE),
|
2020-05-27 18:04:35 +08:00
|
|
|
RetrieveDocument => ErrCode::internal("retrieve_document", StatusCode::BAD_REQUEST),
|
|
|
|
SearchDocuments => ErrCode::internal("search_error", StatusCode::BAD_REQUEST),
|
2020-05-26 19:41:34 +08:00
|
|
|
UnsupportedMediaType => ErrCode::invalid("unsupported_media_type", StatusCode::UNSUPPORTED_MEDIA_TYPE),
|
2020-05-26 01:11:38 +08:00
|
|
|
_ => ErrCode::invalid("other", StatusCode::BAD_REQUEST),
|
2020-05-23 00:04:23 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// return the HTTP status code ascociated with the `Code`
|
2020-05-27 16:20:54 +08:00
|
|
|
fn http(&self) -> StatusCode {
|
2020-05-26 01:11:38 +08:00
|
|
|
self.err_code().status_code
|
2020-05-23 00:04:23 +08:00
|
|
|
}
|
|
|
|
|
2020-05-26 01:11:38 +08:00
|
|
|
/// return error name, used as error code
|
2020-05-27 16:20:54 +08:00
|
|
|
fn name(&self) -> String {
|
2020-05-27 18:04:35 +08:00
|
|
|
self.err_code().error_name.to_string()
|
2020-05-23 00:04:23 +08:00
|
|
|
}
|
|
|
|
|
2020-05-26 01:11:38 +08:00
|
|
|
/// return the error type
|
2020-05-27 16:20:54 +08:00
|
|
|
fn r#type(&self) -> String {
|
2020-05-27 18:04:35 +08:00
|
|
|
self.err_code().error_type.to_string()
|
2020-05-20 00:13:02 +08:00
|
|
|
}
|
2020-05-26 19:41:34 +08:00
|
|
|
|
2020-05-27 16:20:54 +08:00
|
|
|
/// return the doc url ascociated with the error
|
|
|
|
fn url(&self) -> String {
|
2020-05-26 19:41:34 +08:00
|
|
|
format!("docs.meilisearch.come/error/{}", self.name())
|
|
|
|
}
|
2020-05-20 00:13:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Internal structure providing a convenient way to create error codes
|
|
|
|
struct ErrCode {
|
2020-05-26 01:11:38 +08:00
|
|
|
status_code: StatusCode,
|
2020-05-27 18:04:35 +08:00
|
|
|
error_type: ErrorType,
|
|
|
|
error_name: &'static str,
|
2020-05-20 00:13:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ErrCode {
|
2020-05-26 01:11:38 +08:00
|
|
|
|
|
|
|
fn authentication(err_name: &'static str, status_code: StatusCode) -> ErrCode {
|
2020-05-20 00:13:02 +08:00
|
|
|
ErrCode {
|
2020-05-26 01:11:38 +08:00
|
|
|
status_code,
|
2020-05-27 18:04:35 +08:00
|
|
|
error_name: err_name,
|
|
|
|
error_type: ErrorType::Authentication,
|
2020-05-20 00:13:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-26 01:11:38 +08:00
|
|
|
fn internal(err_name: &'static str, status_code: StatusCode) -> ErrCode {
|
|
|
|
ErrCode {
|
|
|
|
status_code,
|
2020-05-27 18:04:35 +08:00
|
|
|
error_name: err_name,
|
|
|
|
error_type: ErrorType::InternalError,
|
2020-05-26 01:11:38 +08:00
|
|
|
}
|
2020-05-23 00:04:23 +08:00
|
|
|
}
|
2020-05-20 00:13:02 +08:00
|
|
|
|
2020-05-26 01:11:38 +08:00
|
|
|
fn invalid(err_name: &'static str, status_code: StatusCode) -> ErrCode {
|
|
|
|
ErrCode {
|
|
|
|
status_code,
|
2020-05-27 18:04:35 +08:00
|
|
|
error_name: err_name,
|
|
|
|
error_type: ErrorType::InvalidRequest,
|
2020-05-26 01:11:38 +08:00
|
|
|
}
|
2020-05-20 00:13:02 +08:00
|
|
|
}
|
|
|
|
}
|