2 个版本
0.3.0 | 2024 年 7 月 5 日 |
---|
#1086 在 网络编程
5,761 每月下载量
在 3 个 Crates 中使用(直接使用 2 个)
46KB
907 行
twirp-rs
Twirp 是一种基于 HTTP 和 Protocol Buffers(proto)的 RPC 协议。该协议使用 HTTP URL 来指定 RPC 端点,并通过 HTTP 请求/响应体发送/接收 proto 消息。服务在 .proto 文件 中定义,使得通过自动生成不同语言的客户端和服务器来轻松实现 RPC 服务。
标准实现是 Go,这是该协议的 Rust 实现。Rust 协议缓冲支持由 prost
生态系统提供。
与 prost-twirp
不同,为服务端和访问 RPC 生成的 trait 是在 async
函数之上实现的。由于在 Rust 1.75 版本之前的 Rust 版本中不支持直接使用包含 async
函数的 trait,因此此 crate 使用 async_trait
宏来封装使它们正常工作所需的所有框架。
用法
查看 示例 以获取完整示例项目。
在 .proto
文件中定义服务和消息
// service.proto
package service.haberdash.v1;
service HaberdasherAPI {
rpc MakeHat(MakeHatRequest) returns (MakeHatResponse);
}
message MakeHatRequest { }
message MakeHatResponse { }
在您的 Cargo.toml
中将 twirp-build
crate 添加为构建依赖项(您还需要 prost-build
)
# Cargo.toml
[build-dependencies]
twirp-build = "0.3"
prost-build = "0.12"
在您的项目中添加一个 build.rs
文件以编译 protos 并生成 Rust 代码
fn main() {
let proto_source_files = ["./service.proto"];
// Tell Cargo to rerun this build script if any of the proto files change
for entry in &proto_source_files {
println!("cargo:rerun-if-changed={}", entry);
}
prost_build::Config::new()
.service_generator(twirp_build::service_generator())
.compile_protos(&proto_source_files, &["./"])
.expect("error compiling protos");
}
这将生成可在 target/build/your-project-*/out/example.service.rs
中找到的代码。为了使用此代码,您需要实现定义的 proto 服务的 trait,并将服务处理器连接到 hyper 网络服务器。请参阅 示例 main.rs
以获取详细信息。
包含生成的代码,创建一个路由器,注册您的服务,然后在 hyper 服务器中提供服务这些路由
mod haberdash {
include!(concat!(env!("OUT_DIR"), "/service.haberdash.v1.rs"));
}
use axum::Router;
use haberdash::{MakeHatRequest, MakeHatResponse};
#[tokio::main]
pub async fn main() {
let api_impl = Arc::new(HaberdasherApiServer {});
let twirp_routes = Router::new()
.nest(haberdash::SERVICE_FQN, haberdash::router(api_impl));
let app = Router::new()
.nest("/twirp", twirp_routes)
.fallback(twirp::server::not_found_handler);
let tcp_listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
if let Err(e) = axum::serve(tcp_listener, app).await {
eprintln!("server error: {}", e);
}
}
// Define the server and implement the trait.
struct HaberdasherApiServer;
#[async_trait]
impl haberdash::HaberdasherApi for HaberdasherApiServer {
async fn make_hat(&self, ctx: twirp::Context, req: MakeHatRequest) -> Result<MakeHatResponse, TwirpErrorResponse> {
todo!()
}
}
此代码创建了一个 axum::Router
,然后将其传递给 axum::serve()
来处理网络。这种使用 axum::serve
的方法是可选的。构建 app
后,您也可以通过导入 twirp::tower::Service
并执行 app.call(request).await
来从任何基于 hyper
的服务器中调用它。
使用方法(客户端)
在客户端,您还将获得一个基于您 proto 中的 rpc 端点的生成的 twirp 客户端。包含生成的代码,创建一个客户端,并开始进行 rpc 调用。
mod haberdash {
include!(concat!(env!("OUT_DIR"), "/service.haberdash.v1.rs"));
}
use haberdash::{HaberdasherApiClient, MakeHatRequest, MakeHatResponse};
#[tokio::main]
pub async fn main() {
let client = Client::from_base_url(Url::parse("https://127.0.0.1:3000/twirp/")?)?;
let resp = client.make_hat(MakeHatRequest { inches: 1 }).await;
eprintln!("{:?}", resp);
}
依赖项
~8–19MB
~278K SLoC