google_androidpublisher_rest/v3/resources/
method_common.rs1use 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#[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#[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#[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
60pub 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}