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("MethodNotAllowed")]
28  MethodNotAllowed(String),
29  #[error("InternalError")]
30  InternalError(String),
31}
32
33/// A helper struct implementing [serde's Serialize trait](Serialize) to allow
34/// easily converting HtsGetErrors to JSON
35#[derive(Serialize)]
36pub struct JsonHtsGetError {
37  error: String,
38  message: String,
39}
40
41/// The "htsget" container wrapping the actual error response above
42#[derive(Serialize)]
43pub struct WrappedHtsGetError {
44  htsget: JsonHtsGetError,
45}
46
47impl HtsGetError {
48  /// Allows converting the error to JSON and the correspondent
49  /// status code
50  pub fn to_json_representation(&self) -> (WrappedHtsGetError, StatusCode) {
51    let (err, status_code) = match self {
52      HtsGetError::InvalidAuthentication(err) => (err, StatusCode::UNAUTHORIZED),
53      HtsGetError::PermissionDenied(err) => (err, StatusCode::FORBIDDEN),
54      HtsGetError::NotFound(err) => (err, StatusCode::NOT_FOUND),
55      HtsGetError::PayloadTooLarge(err) => (err, StatusCode::PAYLOAD_TOO_LARGE),
56      HtsGetError::UnsupportedFormat(err)
57      | HtsGetError::InvalidInput(err)
58      | HtsGetError::InvalidRange(err) => (err, StatusCode::BAD_REQUEST),
59      HtsGetError::MethodNotAllowed(err) => (err, StatusCode::METHOD_NOT_ALLOWED),
60      HtsGetError::InternalError(err) => (err, StatusCode::INTERNAL_SERVER_ERROR),
61    };
62
63    (
64      WrappedHtsGetError {
65        htsget: JsonHtsGetError {
66          error: self.to_string(),
67          message: err.to_string(),
68        },
69      },
70      status_code,
71    )
72  }
73}
74
75impl From<HtsGetSearchError> for HtsGetError {
76  fn from(error: HtsGetSearchError) -> Self {
77    match error {
78      HtsGetSearchError::NotFound(err) => Self::NotFound(err),
79      HtsGetSearchError::UnsupportedFormat(err) => Self::UnsupportedFormat(err),
80      HtsGetSearchError::InvalidInput(err) => Self::InvalidInput(err),
81      HtsGetSearchError::InvalidRange(err) => Self::InvalidRange(err),
82      HtsGetSearchError::IoError(err) | HtsGetSearchError::ParseError(err) => Self::NotFound(err),
83      HtsGetSearchError::InternalError(err) => Self::InternalError(err),
84    }
85  }
86}