Skip to content

Allow custom headers and extensions for twirp clients and servers; unify traits; unify error type #212

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/twirp-build/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "twirp-build"
version = "0.8.0"
version = "0.9.0"
edition = "2021"
description = "Code generation for async-compatible Twirp RPC interfaces."
readme = "README.md"
Expand Down
52 changes: 15 additions & 37 deletions crates/twirp-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ pub fn service_generator() -> Box<ServiceGenerator> {

struct Service {
/// The name of the server trait, as parsed into a Rust identifier.
server_name: syn::Ident,

/// The name of the client trait, as parsed into a Rust identifier.
client_name: syn::Ident,
rpc_trait_name: syn::Ident,

/// The fully qualified protobuf name of this Service.
fqn: String,
Expand All @@ -42,17 +39,15 @@ struct Method {
impl Service {
fn from_prost(s: prost_build::Service) -> Self {
let fqn = format!("{}.{}", s.package, s.proto_name);
let server_name = format_ident!("{}", &s.name);
let client_name = format_ident!("{}Client", &s.name);
let rpc_trait_name = format_ident!("{}", &s.name);
let methods = s
.methods
.into_iter()
.map(|m| Method::from_prost(&s.package, &s.proto_name, m))
.collect();

Self {
server_name,
client_name,
rpc_trait_name,
fqn,
methods,
}
Expand Down Expand Up @@ -102,32 +97,28 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
let output_type = &m.output_type;

trait_methods.push(quote! {
async fn #name(&self, ctx: twirp::Context, req: #input_type) -> Result<#output_type, Self::Error>;
async fn #name(&self, req: twirp::Request<#input_type>) -> twirp::Result<twirp::Response<#output_type>>;
});

proxy_methods.push(quote! {
async fn #name(&self, ctx: twirp::Context, req: #input_type) -> Result<#output_type, Self::Error> {
T::#name(&*self, ctx, req).await
async fn #name(&self, req: twirp::Request<#input_type>) -> twirp::Result<twirp::Response<#output_type>> {
T::#name(&*self, req).await
}
});
}

let server_name = &service.server_name;
let rpc_trait_name = &service.rpc_trait_name;
let server_trait = quote! {
#[twirp::async_trait::async_trait]
pub trait #server_name {
type Error;

pub trait #rpc_trait_name: Send + Sync {
#(#trait_methods)*
}

#[twirp::async_trait::async_trait]
impl<T> #server_name for std::sync::Arc<T>
impl<T> #rpc_trait_name for std::sync::Arc<T>
where
T: #server_name + Sync + Send
T: #rpc_trait_name + Sync + Send
{
type Error = T::Error;

#(#proxy_methods)*
}
};
Expand All @@ -140,16 +131,15 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
let path = format!("/{uri}", uri = m.proto_name);

route_calls.push(quote! {
.route(#path, |api: T, ctx: twirp::Context, req: #input_type| async move {
api.#name(ctx, req).await
.route(#path, |api: T, req: twirp::Request<#input_type>| async move {
api.#name(req).await
})
});
}
let router = quote! {
pub fn router<T>(api: T) -> twirp::Router
where
T: #server_name + Clone + Send + Sync + 'static,
<T as #server_name>::Error: twirp::IntoTwirpResponse
T: #rpc_trait_name + Clone + Send + Sync + 'static
{
twirp::details::TwirpRouterBuilder::new(api)
#(#route_calls)*
Expand All @@ -160,34 +150,22 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
//
// generate the twirp client
//

let client_name = service.client_name;
let mut client_trait_methods = Vec::with_capacity(service.methods.len());
let mut client_methods = Vec::with_capacity(service.methods.len());
for m in &service.methods {
let name = &m.name;
let input_type = &m.input_type;
let output_type = &m.output_type;
let request_path = format!("{}/{}", service.fqn, m.proto_name);

client_trait_methods.push(quote! {
async fn #name(&self, req: #input_type) -> Result<#output_type, twirp::ClientError>;
});

client_methods.push(quote! {
async fn #name(&self, req: #input_type) -> Result<#output_type, twirp::ClientError> {
async fn #name(&self, req: twirp::Request<#input_type>) -> twirp::Result<twirp::Response<#output_type>> {
self.request(#request_path, req).await
}
})
}
let client_trait = quote! {
#[twirp::async_trait::async_trait]
pub trait #client_name: Send + Sync {
#(#client_trait_methods)*
}

#[twirp::async_trait::async_trait]
impl #client_name for twirp::client::Client {
impl #rpc_trait_name for twirp::client::Client {
#(#client_methods)*
}
};
Expand Down
3 changes: 2 additions & 1 deletion crates/twirp/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "twirp"
version = "0.8.0"
version = "0.9.0"
edition = "2021"
description = "An async-compatible library for Twirp RPC in Rust."
readme = "README.md"
Expand All @@ -17,6 +17,7 @@ license-file = "./LICENSE"
test-support = []

[dependencies]
anyhow = "1"
async-trait = "0.1"
axum = "0.8"
futures = "0.3"
Expand Down
4 changes: 1 addition & 3 deletions crates/twirp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,7 @@ struct HaberdasherApiServer;

#[async_trait]
impl haberdash::HaberdasherApi for HaberdasherApiServer {
type Error = TwirpErrorResponse;

async fn make_hat(&self, ctx: twirp::Context, req: MakeHatRequest) -> Result<MakeHatResponse, TwirpErrorResponse> {
async fn make_hat(&self, req: twirp::Request<MakeHatRequest>) -> twirp::Result<twirp::Response<MakeHatResponse>> {
todo!()
}
}
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy