response.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. use std::fmt;
  2. use anyhow::Error;
  3. use bytes::Bytes;
  4. use reqwest::{Response, StatusCode};
  5. use serde::{Deserialize, Serialize};
  6. use serde_json::Value;
  7. use flowy_error::{ErrorCode, FlowyError};
  8. use lib_infra::future::{to_fut, Fut};
  9. #[derive(Debug, Serialize, Deserialize)]
  10. pub struct HttpResponse {
  11. pub data: Bytes,
  12. #[serde(skip_serializing_if = "Option::is_none")]
  13. pub error: Option<HttpError>,
  14. }
  15. #[derive(thiserror::Error, Debug, Serialize, Deserialize, Clone)]
  16. pub struct HttpError {
  17. pub code: ErrorCode,
  18. pub msg: String,
  19. }
  20. impl HttpError {
  21. #[allow(dead_code)]
  22. pub fn is_unauthorized(&self) -> bool {
  23. self.code == ErrorCode::UserUnauthorized
  24. }
  25. }
  26. impl fmt::Display for HttpError {
  27. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  28. write!(f, "{:?}: {}", self.code, self.msg)
  29. }
  30. }
  31. /// Trait `ExtendedResponse` provides an extension method to handle and transform the response data.
  32. ///
  33. /// This trait introduces a single method:
  34. ///
  35. /// - `get_value`: It extracts the value from the response, and returns it as an instance of a type `T`.
  36. /// This method will return an error if the status code of the response signifies a failure (not success).
  37. /// Otherwise, it attempts to parse the response body into an instance of type `T`, which must implement
  38. /// `serde::de::DeserializeOwned`, `Send`, `Sync`, and have a static lifetime ('static).
  39. pub trait ExtendedResponse {
  40. /// Returns the value of the response as a Future of `Result<T, Error>`.
  41. ///
  42. /// If the status code of the response is not a success, returns an `Error`.
  43. /// Otherwise, attempts to parse the response into an instance of type `T`.
  44. ///
  45. /// # Type Parameters
  46. ///
  47. /// * `T`: The type of the value to be returned. Must implement `serde::de::DeserializeOwned`,
  48. /// `Send`, `Sync`, and have a static lifetime ('static).
  49. fn get_value<T>(self) -> Fut<Result<T, Error>>
  50. where
  51. T: serde::de::DeserializeOwned + Send + Sync + 'static;
  52. fn get_bytes(self) -> Fut<Result<Bytes, Error>>;
  53. fn get_json(self) -> Fut<Result<Value, Error>>;
  54. fn success(self) -> Fut<Result<(), Error>>;
  55. fn success_with_body(self) -> Fut<Result<String, Error>>;
  56. }
  57. impl ExtendedResponse for Response {
  58. fn get_value<T>(self) -> Fut<Result<T, Error>>
  59. where
  60. T: serde::de::DeserializeOwned + Send + Sync + 'static,
  61. {
  62. to_fut(async move {
  63. let status_code = self.status();
  64. if !status_code.is_success() {
  65. return Err(parse_response_as_error(self).await.into());
  66. }
  67. let bytes = self.bytes().await?;
  68. let value = serde_json::from_slice(&bytes).map_err(|e| {
  69. FlowyError::new(
  70. ErrorCode::Serde,
  71. format!(
  72. "failed to parse json: {}, body: {}",
  73. e,
  74. String::from_utf8_lossy(&bytes)
  75. ),
  76. )
  77. })?;
  78. Ok(value)
  79. })
  80. }
  81. fn get_bytes(self) -> Fut<Result<Bytes, Error>> {
  82. to_fut(async move {
  83. let status_code = self.status();
  84. if !status_code.is_success() {
  85. return Err(parse_response_as_error(self).await.into());
  86. }
  87. let bytes = self.bytes().await?;
  88. Ok(bytes)
  89. })
  90. }
  91. fn get_json(self) -> Fut<Result<Value, Error>> {
  92. to_fut(async move {
  93. if !self.status().is_success() {
  94. return Err(parse_response_as_error(self).await.into());
  95. }
  96. let bytes = self.bytes().await?;
  97. let value = serde_json::from_slice::<Value>(&bytes)?;
  98. Ok(value)
  99. })
  100. }
  101. fn success(self) -> Fut<Result<(), Error>> {
  102. to_fut(async move {
  103. if !self.status().is_success() {
  104. return Err(parse_response_as_error(self).await.into());
  105. }
  106. Ok(())
  107. })
  108. }
  109. fn success_with_body(self) -> Fut<Result<String, Error>> {
  110. to_fut(async move {
  111. if !self.status().is_success() {
  112. return Err(parse_response_as_error(self).await.into());
  113. }
  114. Ok(self.text().await?)
  115. })
  116. }
  117. }
  118. async fn parse_response_as_error(response: Response) -> FlowyError {
  119. let status_code = response.status();
  120. let msg = response.text().await.unwrap_or_default();
  121. if status_code == StatusCode::CONFLICT {
  122. return FlowyError::new(ErrorCode::Conflict, msg);
  123. }
  124. FlowyError::new(
  125. ErrorCode::HttpError,
  126. format!(
  127. "expected status code 2XX, but got {}, body: {}",
  128. status_code, msg
  129. ),
  130. )
  131. }