AThilenius / axum-connect

Axum + Connect-Web = ♥️
Apache License 2.0
79 stars 6 forks source link

Question #3

Closed rohanmsunmall closed 11 months ago

rohanmsunmall commented 11 months ago
  1. Is there a recommended workflow to multiplex and handle regular axum web requests. I want to handle some webhooks that aren't coming through grpc/connect.
  2. How do you think about this vs https://github.com/hyperium/tonic. Ie is it connect vs grpc or more axum like
AThilenius commented 11 months ago

Hi @rohanmsunmall

Let me answer your questions backwards, because the second one has consequences for the first.

Question 2: Tonic (and any other gRPC server) doesn't work with browsers. gRPC made the really unfortunate choice to require HTTP2 with trailers, without a fallback to HTTP1. Still today there is no standardized way to make HTTP2 calls from JavaScript. That means if you want to call a gRPC endpoint from a web client, you need to use a proxy, which these days usually means grpc-web. It will translate gRPC to HTTP/JSON, but it uses a REALLY ugly, unreadable JSON format. TL;DR: you can't use Tonic with web, not without a proxy, and it's ugly. It's still great for Machine to Machine communication though!

Connect is very different, it's a totally new protocol designed around browsers first. It speaks normal looking JSON over standard HTTP endpoints (doesn't matter if it's HTTP1, H2 or H3). It can optionally also speak binary protobuf over the same transports if you so chose, making it very efficient for M2M communication and interoperable with gRPC servers.

So getting to question 1: you can (and should) mix axum-connect RPC handlers with normal HTTP endpoints, because both of them really are just "normal" HTTP endpoints! Connect uses POST and speaks totally readable JSON. The protocol is very well defined here. This is trivial to do, just register both like this:

pub fn router() -> Router<AppState> {
    Router::new()
        // This is an `axum-connect` RPC
        .rpc(WhoAmIService::who_am_i(whoami_rpc))
        // This is a normal GET/POST handler
        .route("/whoami", get(whoami).post(whoami))
}

Connect has totally transformed gRPC for me, it's actually useful without having to deal with the nightmare that was web interoperability! This project brings that support to idiomatic Rust servers.

rohanmsunmall commented 11 months ago

Totally makes sense. Super helpful! I really appreciate this.

AThilenius commented 11 months ago

You're very welcome. Feel free to re-open this if you have any follow up questions!