reqwest_graphql/
client.rs1use crate::error::{GraphQLError, GraphQLErrorMessage};
2use reqwest::{
3 header::{HeaderMap, HeaderName, HeaderValue},
4 Client,
5};
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::str::FromStr;
9
10pub struct GQLClient<'a> {
11 endpoint: &'a str,
12 header_map: HeaderMap,
13}
14
15#[derive(Serialize)]
16struct RequestBody<'a, T: Serialize> {
17 query: &'a str,
18 variables: T,
19}
20
21#[derive(Deserialize, Debug)]
22struct GraphQLResponse<T> {
23 data: Option<T>,
24 errors: Option<Vec<GraphQLErrorMessage>>,
25}
26
27impl<'a> GQLClient<'a> {
28 pub fn new(endpoint: &'a str) -> Self {
29 Self {
30 endpoint,
31 header_map: HeaderMap::new(),
32 }
33 }
34
35 pub fn new_with_headers(endpoint: &'a str, headers: HashMap<&str, &str>) -> Self {
36 let mut header_map = HeaderMap::new();
37
38 for (str_key, str_value) in headers {
39 let key = HeaderName::from_str(str_key).unwrap();
40 let val = HeaderValue::from_str(str_value).unwrap();
41
42 header_map.insert(key, val);
43 }
44
45 Self {
46 endpoint,
47 header_map,
48 }
49 }
50
51 pub async fn query<K>(&self, query: &'a str) -> Result<K, GraphQLError>
52 where
53 K: for<'de> Deserialize<'de>,
54 {
55 self.query_with_vars::<K, ()>(query, ()).await
56 }
57
58 pub async fn query_with_vars<K, T: Serialize>(
59 &self,
60 query: &'a str,
61 variables: T,
62 ) -> Result<K, GraphQLError>
63 where
64 K: for<'de> Deserialize<'de>,
65 {
66 let client = Client::new();
67 let body = RequestBody { query, variables };
68
69 let request = client
70 .post(self.endpoint)
71 .json(&body)
72 .headers(self.header_map.clone());
73
74 let raw_response = request.send().await?;
75 let json_response = raw_response.json::<GraphQLResponse<K>>().await;
76
77 match json_response {
79 Ok(json) => {
80 if json.errors.is_some() {
82 return Err(GraphQLError::from_json(json.errors.unwrap()));
83 }
84
85 Ok(json.data.unwrap())
86 }
87 Err(_e) => Err(GraphQLError::from_str("Failed to parse response")),
88 }
89 }
90}