htsget_http/
error.rs

1use http::StatusCode;
2use serde::Serialize;
3use thiserror::Error;
4
5use htsget_config::types::HtsGetError as HtsGetSearchError;
6
7pub type Result<T> = core::result::Result<T, HtsGetError>;
8
9/// An error type that describes the errors specified in the
10/// [HtsGet specification](https://samtools.github.io/hts-specs/htsget.html)
11#[derive(Error, Debug, PartialEq, Eq)]
12pub enum HtsGetError {
13  #[error("InvalidAuthentication")]
14  InvalidAuthentication(String),
15  #[error("PermissionDenied")]
16  PermissionDenied(String),
17  #[error("NotFound")]
18  NotFound(String),
19  #[error("PayloadTooLarge")]
20  PayloadTooLarge(String),
21  #[error("UnsupportedFormat")]
22  UnsupportedFormat(String),
23  #[error("InvalidInput")]
24  InvalidInput(String),
25  #[error("InvalidRange")]
26  InvalidRange(String),
27  #[error("InternalError")]
28  InternalError(String),
29}
30
31/// A helper struct implementing [serde's Serialize trait](Serialize) to allow
32/// easily converting HtsGetErrors to JSON
33#[derive(Serialize)]
34pub struct JsonHtsGetError {
35  error: String,
36  message: String,
37}
38
39/// The "htsget" container wrapping the actual error response above
40#[derive(Serialize)]
41pub struct WrappedHtsGetError {
42  htsget: JsonHtsGetError,
43}
44
45impl HtsGetError {
46  /// Allows converting the error to JSON and the correspondent
47  /// status code
48  pub fn to_json_representation(&self) -> (WrappedHtsGetError, StatusCode) {
49    let (err, status_code) = match self {
50      HtsGetError::InvalidAuthentication(err) => (err, StatusCode::UNAUTHORIZED),
51      HtsGetError::PermissionDenied(err) => (err, StatusCode::FORBIDDEN),
52      HtsGetError::NotFound(err) => (err, StatusCode::NOT_FOUND),
53      HtsGetError::PayloadTooLarge(err) => (err, StatusCode::PAYLOAD_TOO_LARGE),
54      HtsGetError::UnsupportedFormat(err)
55      | HtsGetError::InvalidInput(err)
56      | HtsGetError::InvalidRange(err) => (err, StatusCode::BAD_REQUEST),
57      HtsGetError::InternalError(err) => (err, StatusCode::INTERNAL_SERVER_ERROR),
58    };
59
60    (
61      WrappedHtsGetError {
62        htsget: JsonHtsGetError {
63          error: self.to_string(),
64          message: err.to_string(),
65        },
66      },
67      status_code,
68    )
69  }
70}
71
72impl From<HtsGetSearchError> for HtsGetError {
73  fn from(error: HtsGetSearchError) -> Self {
74    match error {
75      HtsGetSearchError::NotFound(err) => Self::NotFound(err),
76      HtsGetSearchError::UnsupportedFormat(err) => Self::UnsupportedFormat(err),
77      HtsGetSearchError::InvalidInput(err) => Self::InvalidInput(err),
78      HtsGetSearchError::InvalidRange(err) => Self::InvalidRange(err),
79      HtsGetSearchError::IoError(err) | HtsGetSearchError::ParseError(err) => Self::NotFound(err),
80      HtsGetSearchError::InternalError(err) => Self::InternalError(err),
81    }
82  }
83}