【conreg-client】在Rust中使用向Feign一样的远程调用

conreg-client 0.2.0-beta.2版本发布啦,支持创建声明式的 HTTP 客户端,类似于 Java Feign。通过为 trait 添加#[feign_client],可自动生成 HTTP 请求的实现代码,实现微服务之间的 HTTP 通信。

文档地址:https://docs.rs/conreg-client/0.2.0-beta.2/conreg_client/

使用方式:

toml 复制代码
conreg-client = { version = "=0.2.0-beta.2", features = ["tracing", "feign"]}

示例:

rust 复制代码
#[feign_client(service_id = "test-server")]
trait ExampleClient {
    /// Request `GET` and return string.
    #[get("/hello")]
    async fn hello(&self) -> Result<String, FeignError>;
}

#[tokio::main]
async fn main() {
    conreg_client::init().await;
  
    let client = ExampleClientImpl::default();

    let response = client.hello().await.unwrap();
    println!("hello -> {:?}", response);
}

feign_client

feign_client 宏作用于一个trait,它接收以下参数:

  • service_id:必填,服务的唯一标识符,用于服务发现和负载均衡。
  • base_path:可选,基础路径前缀,将添加到所有请求路径之前。
  • url:可选,直接指定请求的 URL,如果设置了此项,将忽略 service_idbase_path

feign_client 将自动实现其标记的trait,生成 <trait_name>Impl 的默认实现。

参数绑定

路径参数

在路径中使用 {param_name} 占位符。当方法参数名与占位符名称匹配时,会自动绑定。

示例:#[get("/api/users/{id}")]

查询参数

使用 query = "{param}" 指定查询参数模板。

示例:#[get(path = "/api/users", query = "id={id}")]

表单参数

form 虽然在服务间调用时并不常用,但是也支持,该参数类型必须为reqwest::multipart::Form

使用 form = "{param}" 指定表单数据,支持 application/x-www-form-urlencodedmultipart/form-data

示例:#[post(path = "/api/login", form = "{loginForm}")]

请求体参数

使用 body = "{param}" 指定原始请求体,请求体类型必须实现了Into<reqwest::Body>

示例:#[post(path = "/api/post", body = "{data}")]

JSON 参数

使用 json = "{param}" 指定 JSON 数据;会自动序列化并设置 Content-Type: application/json

示例:#[post(path = "/api/post", json = "{data}")]

JSON的序列化和反序列化依赖于 serde_json

请求头

使用 headers("Key=Value", ...)headers("Key={param}", ...) 指定请求头,支持静态值和动态参数。

示例:#[get(path = "/api/users", headers("Authorization=Bearer {token}", "Accept=application/json"))]

示例

以下是一个较为完整的示例:

rust 复制代码
#[feign_client(service_id = "httpbin", url = "https://httpbin.org")]
trait ExampleClient {
   /// Request `GET` and return string.
   #[get("/ip")]
   async fn ip(&self) -> Result<String, FeignError>;

   /// Request `GET` and return json.
   #[get(path = "/json")]
   async fn json(&self) -> Result<serde_json::Value, FeignError>;

   /// Request `GET` and return bytes.
   #[get(path = "/image", headers("Accept=image/png"))]
   async fn image(&self) -> Result<Bytes, FeignError>;

   /// Post a form
   #[post(path = "/post", form = "{form}")]
   async fn form(&self, form: Form) -> Result<String, FeignError>;

   /// 动态Header
   #[get(path = "/headers", headers("My-Header={my_header}"))]
   async fn headers(&self, my_header: &str) -> Result<String, FeignError>;
}

#[tokio::main]
async fn main() {
   let client = ExampleClientImpl::default();

   let response = client.ip().await.unwrap();
   println!("ip -> {:?}", response);

   let response = client.json().await.unwrap();
   println!("json -> {:#?}", response);

   let response = client.image().await.unwrap();
   let path = Path::new("image.png");
   std::fs::write(&path, response).unwrap();
   println!("image saved -> {:?}", path.canonicalize().unwrap());

   let form = Form::new().text("custname", "Hello, this is form form!");
   let response = client.form(form).await.unwrap();
   println!("form -> {:?}", response);

   let response = client.headers("Hello, this is headers!").await.unwrap();
   println!("headers -> {:?}", response);
}

使用限制

目前 conreg-client 仍处于早期阶段,未来API可能会有较大变化,目前还不建议用于生产环境。欢迎对此项目感兴趣的同学来一起改进。

仓库地址:conreg

相关推荐
爱研究的小梁19 小时前
告别实验室理想网络,真实场景下具身智能远程操控怎么干?
网络·人工智能·机器人·信息与通信
程序员若风19 小时前
CSRF攻击原理介绍和利用-腾讯云开发者社区
前端·网络·安全·web安全·网络安全·csrf攻击·腾讯云开发者社区
曼巴UE520 小时前
UE5 客户端 需要的网络同步概念总结(3 )-事件同步 RPC 以及三种调用方式
网络·c++·网络协议·学习·rpc·ue5
captain37620 小时前
HTTP(2)
java·网络·http·java-ee
万联WANFLOW20 小时前
94%成交引爆美区:TikTok直播电商迎来高客单价时代
网络·业界资讯
xiaoye-duck20 小时前
《Linux 网络编程》深入理解数据链路层:从MAC帧到ARP协议的底层原理详解
linux·网络
开开心心就好20 小时前
安卓手写文字生成工具,多种纸张一直免费
网络·网络协议·tcp/ip·leetcode·智能手机·电脑·模拟退火算法
比兔代理1 天前
正向代理与反向代理技术辨析,为什么代理 IP 属于正向代理
服务器·网络·http·ip
Ivanqhz1 天前
SVD++算法
java·服务器·网络·深度学习·神经网络
迪康Defender1 天前
终端安全实战:如何高效解决企业U盘泄密与管控难题
运维·网络·安全·web安全·终端安全管理