meilisearch/meilisearch-error/src/lib.rs

179 lines
5.7 KiB
Rust
Raw Normal View History

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
}
}