hyperium / tonic

A native gRPC client & server implementation with async/await support.
https://docs.rs/tonic
MIT License
9.82k stars 999 forks source link

Adding an IntoResponse trait #1416

Open dae opened 1 year ago

dae commented 1 year ago

Feature Request

Crates

tonic-build

Motivation

When using a generated client, you can pass either a Message or a Request<Message>, as the client accepts impl IntoRequest. This makes things more ergonomic when you don't have any headers/options to attach.

The generated server code lacks a similar IntoResponse and IntoStreamingResponse trait, so all responses need to be wrapped in Response::new(). This makes things a bit more cumbersome, and inconsistent with the client side of things (I remember being a bit confused by this when I started using Tonic).

Are there any technical limitations or other reasons that would prevent adding such functionality in the next breaking update?

(Apologies if this has been discussed before. I found a brief mention on https://github.com/hyperium/tonic/pull/66#issuecomment-545213939 but couldn't see an issue for this specifically)

Proposal

Adding a similar trait:

pub trait IntoResponse<T> {
    fn into_response(self) -> Response<T>;
}

impl<T> IntoResponse<T> for T {
    fn into_response(self) -> Response<Self> {
        Response::new(self)
    }
}

impl<T> IntoResponse<T> for Response<T> {
    fn into_response(self) -> Response<T> {
        self
    }
}

async fn some_method(...) -> Result<impl IntoResponse<SomeMessage>, tonic::Status> {
    Ok(Response::new(SomeMessage {}))
}

async fn some_method(...) -> Result<impl IntoResponse<SomeMessage>, tonic::Status> {
    Ok(SomeMessage {})
}

prost-build would presumably need to be updated to change the signature of the generated methods, and call .into_response() inside call().

One potential downside is increased compile time due to the extra type inferences, but such a cost is already paid when compiling the client.

If this is something you'd be amenable to, I can look into it further.

Alternatives

https://github.com/hyperium/tonic/pull/1064 would continue to require manual wrapping, but would reduce the keystrokes required to do so.

aviramha commented 8 months ago

Hey, I just stumbled upon the same annoyance - would love to see this - also Into<Status> is helpful since then we can implement our own error type and provide Into implementation for it.