use clap::ValueEnum;
use reqwest::{Client, RequestBuilder};
use serde_json::Value;
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum Transport {
#[value(name = "auto")]
Auto,
#[value(name = "post-json")]
PostJson,
#[value(name = "get")]
Get,
#[value(name = "form")]
Form,
#[value(name = "graphql")]
Graphql,
}
pub fn build_graphql_request(
client: &Client,
url: &str,
transport: Transport,
query: &str,
variables: Option<&Value>,
is_mutation: bool,
) -> RequestBuilder {
match transport {
Transport::PostJson | Transport::Auto => post_json_request(client, url, query, variables),
Transport::Get => {
if is_mutation {
return post_json_request(client, url, query, variables);
}
let mut params: Vec<(&str, String)> = vec![("query", query.to_string())];
if let Some(vars) = variables {
if !vars.is_null() {
params.push(("variables", vars.to_string()));
}
}
client.get(url).query(¶ms)
}
Transport::Form => {
let mut body = format!("query={}", urlencoding::encode(query));
if let Some(vars) = variables {
if !vars.is_null() {
body.push_str(&format!("&variables={}", urlencoding::encode(&vars.to_string())));
}
}
client
.post(url)
.header("Content-Type", "application/x-www-form-urlencoded")
.body(body)
}
Transport::Graphql => {
client
.post(url)
.header("Content-Type", "application/graphql")
.body(query.to_string())
}
}
}
fn post_json_request(client: &Client, url: &str, query: &str, variables: Option<&Value>) -> RequestBuilder {
let body = match variables {
Some(vars) => serde_json::json!({ "query": query, "variables": vars }),
None => serde_json::json!({ "query": query }),
};
client.post(url).header("Content-Type", "application/json").json(&body)
}