Rust GraphQL客户端工具graphql_client_cli的使用,支持高效查询与代码自动生成

Rust GraphQL客户端工具graphql_client_cli的使用,支持高效查询与代码自动生成

安装

cargo install graphql_client_cli --force

获取Schema

从运行的GraphQL API获取schema,schema会输出到stdout。

graphql-client introspect-schema [FLAGS] [OPTIONS] <schema_location>

参数说明:

FLAGS:
    -h, --help       显示帮助信息
    -V, --version    显示版本信息
        --no-ssl     禁用SSL证书验证(默认false)

OPTIONS:
        --authorization <authorization>    设置Authorization头内容
        --header <headers>...              指定自定义头(格式: 'X-Name: Value')
        --output <output>                  指定输出JSON schema的路径

ARGS:
    <schema_location>    GraphQL端点URL

生成客户端代码

graphql-client generate [FLAGS] [OPTIONS] <query_path> --schema-path <schema_path>

参数说明:

FLAGS:
    -h, --help            显示帮助信息
        --no-formatting   不执行rustfmt格式化生成的代码(默认false)
    -V, --version         显示版本信息

OPTIONS:
    -I, --variables-derives <variables_derives>
            为变量生成的struct和enum添加额外的derive(例: --variables-derives='Serialize,PartialEq')
    -O, --response-derives <response_derives>
            为响应生成的struct和enum添加额外的derive(例: --response-derives='Serialize,PartialEq')
    -d, --deprecation-strategy <deprecation_strategy>
            选择弃用策略: allow, deny或warn(默认warn)
    -m, --module-visibility <module_visibility>
            选择模块和结构体可见性: pub或private(默认pub)
    -o, --output-directory <output_directory>
            代码生成的目标目录
    -s, --schema-path <schema_path>
            GraphQL schema文件路径(.json或.graphql)
    -o, --selected-operation <selected_operation>
            目标查询名称。如果不设置此参数,则生成query文件中的所有查询
    --fragments-other-variant
            为fragment生成的enum添加Unknown变体

ARGS:
    <query_path>    GraphQL查询文件路径

如果要使用格式化功能,需要这样安装:

cargo install graphql_client_cli

完整示例

示例1:获取GraphQL Schema

# 从GitHub API获取schema并保存到schema.json
graphql-client introspect-schema https://api.github.com/graphql \
  --output schema.json \
  --header "Authorization: bearer YOUR_GITHUB_TOKEN"

示例2:生成客户端代码

首先创建一个查询文件 query.graphql

query GetUser($login: String!) {
  user(login: $login) {
    login
    name
    bio
    location
    websiteUrl
  }
}

然后运行生成命令:

graphql-client generate query.graphql \
  --schema-path schema.json \
  --output-directory src/graphql \
  --variables-derives "Serialize,Deserialize" \
  --response-derives "Serialize,Deserialize"

这将在 src/graphql 目录生成Rust客户端代码。

示例3:使用生成的客户端代码

use graphql_client::{GraphQLQuery, Response};
use serde_json::json;

#[derive(GraphQLQuery)]
#[graphql(
    schema_path = "schema.json",
    query_path = "query.graphql",
    response_derives = "Debug,Serialize,Deserialize",
    variables_derives = "Debug,Serialize,Deserialize"
)]
pub struct GetUser;

async fn fetch_user(login: String) -> Result<(), reqwest::Error> {
    let variables = get_user::Variables { login };
    let request_body = GetUser::build_query(variables);
    
    let client = reqwest::Client::new();
    let res = client
        .post("https://api.github.com/graphql")
        .header("Authorization", "bearer YOUR_GITHUB_TOKEN")
        .json(&request_body)
        .send()
        .await?;
        
    let response_body: Response<get_user::ResponseData> = res.json().await?;
    println!("{:?}", response_body.data);
    
    Ok(())
}

完整示例demo

以下是基于上述示例的完整demo:

// 主要依赖
use graphql_client::{GraphQLQuery, Response};
use reqwest;
use serde_json;

// 定义查询结构体
#[derive(GraphQLQuery)]
#[graphql(
    schema_path = "schema.json",  // schema文件路径
    query_path = "query.graphql", // 查询文件路径
    response_derives = "Debug,Serialize,Deserialize",  // 响应结构体derive
    variables_derives = "Debug,Serialize,Deserialize"  // 变量结构体derive
)]
pub struct GetUser;

// 异步函数获取用户信息
async fn fetch_github_user(login: String) -> Result<(), reqwest::Error> {
    // 构造查询变量
    let variables = get_user::Variables { login };
    
    // 构建查询请求体
    let request_body = GetUser::build_query(variables);
    
    // 创建HTTP客户端
    let client = reqwest::Client::new();
    
    // 发送请求并获取响应
    let res = client
        .post("https://api.github.com/graphql")
        .header("Authorization", "bearer YOUR_GITHUB_TOKEN")  // 替换为你的token
        .json(&request_body)
        .send()
        .await?;
    
    // 解析响应数据
    let response_body: Response<get_user::ResponseData> = res.json().await?;
    
    // 打印用户数据
    if let Some(data) = response_body.data {
        println!("用户登录名: {}", data.user.login);
        println!("用户名: {}", data.user.name.unwrap_or_default());
        println!("用户简介: {}", data.user.bio.unwrap_or_default());
        println!("用户位置: {}", data.user.location.unwrap_or_default());
        println!("个人网站: {}", data.user.website_url.unwrap_or_default());
    }
    
    Ok(())
}

// 主函数
#[tokio::main]
async fn main() {
    match fetch_github_user("octocat".to_string()).await {  // 查询octocat用户信息
        Ok(_) => println!("查询成功!"),
        Err(e) => eprintln!("查询失败: {:?}", e),
    }
}

这个完整demo展示了如何:

  1. 使用graphql_client_cli工具生成客户端代码
  2. 定义GraphQL查询结构体
  3. 构建查询请求
  4. 处理响应数据
  5. 在主函数中调用查询函数

要运行这个demo,你需要:

  1. 按照前面的步骤获取GitHub API的schema
  2. 创建query.graphql文件
  3. 生成客户端代码
  4. 替换YOUR_GITHUB_TOKEN为有效的GitHub token

1 回复

Rust GraphQL客户端工具graphql_client_cli使用指南

完整示例demo

下面是一个完整的示例,展示如何使用graphql_client_cli从GraphQL API获取用户信息:

  1. 首先创建一个GraphQL schema文件 schema.graphql:
type User {
  id: ID!
  name: String!
  email: String!
  posts: [Post!]!
}

type Post {
  id: ID!
  title: String!
  content: String!
  publishedAt: DateTime!
}

type Query {
  user(id: ID!): User
}

scalar DateTime
  1. 创建查询文件 queries/get_user.graphql:
query GetUser($id: ID!) {
  user(id: $id) {
    id
    name
    email
    posts {
      title
      publishedAt
    }
  }
}
  1. 生成Rust代码:
graphql_client_cli --schema schema.graphql --output src/graphql --query queries/get_user.graphql --module
  1. 创建build.rs文件:
fn main() {
    println!("cargo:rerun-if-changed=queries/");
    println!("cargo:rerun-if-changed=schema.graphql");
    
    let status = std::process::Command::new("graphql_client_cli")
        .args(&["--schema", "schema.graphql", "--output", "src/graphql", "--query", "queries/", "--module"])
        .status()
        .expect("Failed to run graphql_client_cli");
    
    if !status.success() {
        panic!("GraphQL code generation failed");
    }
}
  1. 创建src/graphql/mod.rs文件:
pub mod get_user;
  1. 主程序src/main.rs:
use graphql_client::{GraphQLQuery, Response};
use std::error::Error;

#[derive(GraphQLQuery)]
#[graphql(
    schema_path = "schema.graphql",
    query_path = "queries/get_user.graphql",
    response_derives = "Debug, Serialize, Deserialize"
)]
pub struct GetUser;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // 准备查询变量
    let variables = get_user::Variables {
        id: "123".to_string(),
    };
    
    // 构建查询请求体
    let request_body = GetUser::build_query(variables);
    
    // 创建HTTP客户端
    let client = reqwest::Client::new();
    
    // 发送请求到GraphQL端点
    let res = client.post("http://example.com/graphql")
        .json(&request_body)
        .send()
        .await?;
    
    // 解析响应
    let response_body: Response<get_user::ResponseData> = res.json().await?;
    
    // 处理响应数据
    if let Some(data) = response_body.data {
        println!("User: {:?}", data.user);
    }
    
    Ok(())
}
  1. 添加必要的依赖到Cargo.toml:
[dependencies]
graphql_client = "0.11"
reqwest = { version = "0.11", features = ["json"] }
tokio = { version = "1.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
  1. 配置文件graphql_client.toml(可选):
[scalars]
DateTime = "chrono::DateTime<chrono::Utc>"

这个完整示例展示了如何:

  • 定义GraphQL schema和查询
  • 自动生成类型安全的Rust代码
  • 集成到Rust项目中
  • 发送GraphQL请求并处理响应
  • 配置自定义标量类型

你可以根据需要修改查询、schema和请求处理逻辑来适应你的具体项目需求。

回到顶部