reqwest_graphql/
client.rs

1use 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        // Check whether JSON is parsed successfully
78        match json_response {
79            Ok(json) => {
80                // Check if error messages have been received
81                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}