josh_github_graphql/
request.rs1use anyhow::{anyhow, Context};
2use graphql_client::GraphQLQuery;
3use http::header;
4
5use crate::connection::GithubApiConnection;
6
7pub const GITHUB_ACCEPT: &str = "application/vnd.github+json";
8pub const GITHUB_REST_API_URL: &str = "https://api.github.com";
9pub const GITHUB_GRAPHQL_API_URL: &str = "https://api.github.com/graphql";
10pub const GITHUB_API_VERSION: &str = "2022-11-28";
11
12pub const JOSH_API_USER_AGENT: &str = "josh-project";
13
14impl GithubApiConnection {
15 async fn do_send_request(&self, body: serde_json::Value) -> anyhow::Result<serde_json::Value> {
18 let builder = self
19 .client
20 .post(self.api_url.clone())
21 .header(header::USER_AGENT, JOSH_API_USER_AGENT)
22 .header(header::ACCEPT, GITHUB_ACCEPT);
23
24 let response = builder
25 .header("X-GitHub-Api-Version", GITHUB_API_VERSION)
26 .header("X-Github-Next-Global-ID", "1")
27 .json(&body)
28 .send()
29 .await?;
30
31 let status = response.status();
32 if status.is_success() {
33 let response_body = response.json().await?;
34 Ok(response_body)
35 } else {
36 let response_body = response.text().await?;
37 let message = format!(
38 "Unexpected status code while making request: {} {}",
39 self.api_url, status
40 );
41
42 if response_body.trim().is_empty() {
43 Err(anyhow!(message))
44 } else {
45 Err(anyhow!("{}, body: {}", message, response_body))
46 }
47 }
48 }
49
50 pub(crate) async fn make_request<T: GraphQLQuery>(
51 &self,
52 variables: T::Variables,
53 ) -> anyhow::Result<T::ResponseData> {
54 let request_body = T::build_query(variables);
55 let request_body = serde_json::to_value(&request_body)?;
56
57 let response = self.do_send_request(request_body).await?;
58 let response_body: graphql_client::Response<T::ResponseData> =
59 serde_json::from_value(response).context("Failed to parse response body")?;
60
61 if let Some(errors) = response_body.errors {
62 let message = errors
63 .iter()
64 .map(|error| error.message.clone())
65 .collect::<Vec<_>>()
66 .join(", ");
67
68 return Err(anyhow!("GraphQL request failed: {:?}", message));
69 }
70
71 response_body.data.context("Response data is missing")
72 }
73}