use futures_lite::future::block_on;
use graphql_client::QueryBody;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize)]
struct UserVariables {
id: String,
}
#[derive(Debug, Deserialize)]
struct GraphqlEnvelope<T> {
data: Option<T>,
errors: Option<Vec<GraphqlError>>,
}
#[derive(Debug, Deserialize)]
struct GraphqlError {
message: String,
}
#[derive(Debug, Deserialize)]
struct UserQueryData {
user: User,
}
#[derive(Debug, Deserialize)]
struct User {
id: String,
name: String,
}
const USER_QUERY: &str = r#"
query UserById($id: ID!) {
user(id: $id) {
id
name
}
}
"#;
fn main() -> Result<(), Box<dyn std::error::Error>> {
block_on(async move {
let client = ugi::Client::builder()
.base_url("https://api.example.com")?
.bearer_auth("token")?
.prefer_http2()
.build()?;
let body = QueryBody {
variables: UserVariables {
id: "user_123".to_owned(),
},
query: USER_QUERY,
operation_name: "UserById",
};
let response: GraphqlEnvelope<UserQueryData> = client
.post("/graphql")
.header(
"accept",
"application/graphql-response+json, application/json",
)?
.json(&body)?
.await?
.json()
.await?;
if let Some(errors) = response.errors {
return Err(format!("graphql error: {}", errors[0].message).into());
}
let data = response
.data
.ok_or_else(|| "graphql response missing data".to_owned())?;
println!("user {} {}", data.user.id, data.user.name);
Ok(())
})
}