1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
use serde::de::DeserializeOwned; use serde_json; use serde_json::value::Value; use url::Url; use reqwest::{Body, Client}; use super::crypt; use super::error::{Error, Result}; use super::method::Method; use super::response::{Response, Stat}; use super::Credentials; use super::Endpoint; pub fn request<T>( client: &Client, endpoint: Endpoint, method: Method, body: Option<Value>, credentials: Option<&Credentials>, ) -> Result<T> where T: DeserializeOwned, { let mut body = serde_json::to_string(&build_body(body, credentials))?; if method.is_encrypted() { if let Some(credentials) = credentials { body = crypt::encrypt(credentials.encrypt_key(), &body); } } let url = build_url(client, endpoint, method, credentials); let mut res_post = client .post(&url.to_string()) .body(Body::from(body)) .send()?; let res: Response<T> = res_post.json()?; match res { Response { stat: Stat::Ok, result: Some(result), .. } => Ok(result), Response { stat: Stat::Ok, result: None, .. } => Err(Error::Io(<std::io::Error>::new( std::io::ErrorKind::NotFound, "Result not found.", ))), Response { stat: Stat::Fail, .. } => Err(Error::Api { message: res.message.unwrap(), code: res.code.unwrap().into(), }), } } fn build_body(body: Option<Value>, credentials: Option<&Credentials>) -> Value { let mut body = match body { Some(body) => body, None => serde_json::to_value(serde_json::Map::<String, Value>::new()) .expect("Fatal error building body."), }; if let Some(credentials) = credentials { if let Some(obj) = body.as_object_mut() { if let Some(partner_auth_token) = credentials.partner_auth_token() { obj.insert( "partnerAuthToken".to_owned(), Value::String(partner_auth_token.to_owned()), ); } if let Some(sync_time) = credentials.sync_time() { obj.insert("syncTime".to_owned(), Value::from(*sync_time)); } if let Some(user_auth_token) = credentials.user_auth_token() { obj.insert( "userAuthToken".to_owned(), Value::String(user_auth_token.to_owned()), ); } } } body } fn build_url( client: &Client, endpoint: Endpoint, method: Method, credentials: Option<&Credentials>, ) -> Url { let url = format!("{}?method={}", endpoint.to_string(), method.to_string()); let mut url = Url::parse(&url).unwrap(); if let Some(credentials) = credentials { use std::collections::BTreeMap; let mut query_pairs: BTreeMap<&str, &str> = BTreeMap::new(); if let Some(partner_auth_token) = credentials.partner_auth_token() { query_pairs.insert("auth_token", partner_auth_token); } if let Some(user_auth_token) = credentials.user_auth_token() { query_pairs.insert("auth_token", user_auth_token); } if let Some(partner_id) = credentials.partner_id() { query_pairs.insert("partner_id", partner_id); } if let Some(user_id) = credentials.user_id() { query_pairs.insert("user_id", user_id); } url.query_pairs_mut().extend_pairs(query_pairs); } url }