Skip to main content

google_androidpublisher_rest/v3/resources/
method_common.rs

1use core::fmt;
2
3use http_api_client_endpoint::{
4    http::{Error as HttpError, StatusCode},
5    Body, Response,
6};
7use serde::{de::DeserializeOwned, Deserialize, Serialize};
8use serde_json::Error as SerdeJsonError;
9
10//
11//
12//
13#[derive(Debug, Clone)]
14pub enum MethodEndpointRet<T>
15where
16    T: fmt::Debug + Clone,
17{
18    Ok(T),
19    Other((StatusCode, Result<MethodResponseErrorBody, Body>)),
20}
21
22//
23//
24//
25#[derive(thiserror::Error, Debug)]
26pub enum MethodEndpointError {
27    #[error("SerRequestBodyFailed {0}")]
28    SerRequestBodyFailed(SerdeJsonError),
29    #[error("MakeRequestFailed {0}")]
30    MakeRequestFailed(HttpError),
31    #[error("DeResponseBodyFailed {0}")]
32    DeResponseBodyFailed(SerdeJsonError),
33}
34
35//
36//
37//
38#[derive(Serialize, Deserialize, Debug, Clone)]
39pub struct MethodResponseErrorBody {
40    pub error: MethodResponseErrorBodyError,
41}
42
43#[derive(Serialize, Deserialize, Debug, Clone)]
44pub struct MethodResponseErrorBodyError {
45    pub errors: Vec<MethodResponseErrorBodyErrorError>,
46    pub code: usize,
47    pub message: String,
48}
49
50#[derive(Serialize, Deserialize, Debug, Clone)]
51#[serde(rename_all = "camelCase")]
52pub struct MethodResponseErrorBodyErrorError {
53    pub domain: String,
54    pub reason: String,
55    pub message: String,
56    pub location_type: Option<String>,
57    pub location: Option<String>,
58}
59
60//
61//
62//
63pub fn method_endpoint_parse_response<T>(
64    response: Response<Body>,
65) -> Result<MethodEndpointRet<T>, MethodEndpointError>
66where
67    T: fmt::Debug + Clone + DeserializeOwned,
68{
69    let status = response.status();
70    match status {
71        StatusCode::OK => {
72            let ok_json = serde_json::from_slice::<T>(response.body())
73                .map_err(MethodEndpointError::DeResponseBodyFailed)?;
74
75            Ok(MethodEndpointRet::Ok(ok_json))
76        }
77        status => match serde_json::from_slice::<MethodResponseErrorBody>(response.body()) {
78            Ok(err_json) => Ok(MethodEndpointRet::Other((status, Ok(err_json)))),
79            Err(_) => Ok(MethodEndpointRet::Other((
80                status,
81                Err(response.body().to_owned()),
82            ))),
83        },
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90
91    #[test]
92    fn de_response_error_body() {
93        match serde_json::from_str::<MethodResponseErrorBody>(include_str!(
94            "../../../tests/response_body_files/err__400.json"
95        )) {
96            Ok(body) => {
97                assert_eq!(body.error.errors.len(), 1);
98                let err = body.error.errors.first().unwrap();
99                assert_eq!(err.domain, "global");
100                assert_eq!(err.reason, "invalid");
101                assert_eq!(err.message, "Invalid Value");
102                assert_eq!(err.location_type, None);
103                assert_eq!(err.location, None);
104                assert_eq!(body.error.code, 400);
105                assert_eq!(body.error.message, "Invalid Value");
106            }
107            Err(err) => panic!("{}", err),
108        }
109
110        match serde_json::from_str::<MethodResponseErrorBody>(include_str!(
111            "../../../tests/response_body_files/err__404.json"
112        )) {
113            Ok(body) => {
114                assert_eq!(body.error.errors.len(), 1);
115                let err = body.error.errors.first().unwrap();
116                assert_eq!(err.location_type, Some("parameter".to_owned()));
117                assert_eq!(err.location, Some("packageName".to_owned()));
118            }
119            Err(err) => panic!("{}", err),
120        }
121    }
122}