#rpc #grpc #grpc-web

tonic-web

grpc-web protocol translation for tonic services

5 releases (breaking)

0.5.0 Nov 28, 2022
0.4.0 Jul 29, 2022
0.3.0 Apr 1, 2022
0.2.0 Oct 25, 2021
0.1.0 Jul 8, 2021

#2606 in Network programming

Download history 3336/week @ 2022-11-29 3265/week @ 2022-12-06 3168/week @ 2022-12-13 2086/week @ 2022-12-20 1992/week @ 2022-12-27 3045/week @ 2023-01-03 3136/week @ 2023-01-10 3162/week @ 2023-01-17 7036/week @ 2023-01-24 6680/week @ 2023-01-31 3243/week @ 2023-02-07 3091/week @ 2023-02-14 5004/week @ 2023-02-21 3840/week @ 2023-02-28 3633/week @ 2023-03-07 3602/week @ 2023-03-14

16,412 downloads per month
Used in 13 crates (9 directly)

MIT license

455KB
9K SLoC

tonic-web

Enables tonic servers to handle requests from grpc-web clients directly, without the need of an external proxy.

Getting Started

[dependencies]
tonic-web = "<tonic-web-version>"

Enabling tonic services

The easiest way to get started, is to call the function with your tonic service and allow the tonic server to accept HTTP/1.1 requests:

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let addr = "[::1]:50051".parse().unwrap();
    let greeter = GreeterServer::new(MyGreeter::default());

    Server::builder()
       .accept_http1(true)
       .add_service(tonic_web::enable(greeter))
       .serve(addr)
       .await?;

   Ok(())
}

Examples

See the examples folder for a server and client example.


lib.rs:

grpc-web protocol translation for tonic services.

tonic_web enables tonic servers to handle requests from grpc-web clients directly, without the need of an external proxy. It achieves this by wrapping individual tonic services with a tower service that performs the translation between protocols and handles cors requests.

Getting Started

[dependencies]
tonic_web = "0.1"

Enabling tonic services

The easiest way to get started, is to call the enable function with your tonic service and allow the tonic server to accept HTTP/1.1 requests:

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let addr = "[::1]:50051".parse().unwrap();
    let greeter = GreeterServer::new(MyGreeter::default());

    Server::builder()
       .accept_http1(true)
       .add_service(tonic_web::enable(greeter))
       .serve(addr)
       .await?;

   Ok(())
}

This will apply a default configuration that works well with grpc-web clients out of the box.

You can customize the CORS configuration composing the [GrpcWebLayer] with the cors layer of your choice.

Alternatively, if you have a tls enabled server, you could skip setting accept_http1 to true. This works because the browser will handle ALPN.

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let cert = tokio::fs::read("server.pem").await?;
    let key = tokio::fs::read("server.key").await?;
    let identity = Identity::from_pem(cert, key);

    let addr = "[::1]:50051".parse().unwrap();
    let greeter = GreeterServer::new(MyGreeter::default());

    // No need to enable HTTP/1
    Server::builder()
       .tls_config(ServerTlsConfig::new().identity(identity))?
       .add_service(tonic_web::enable(greeter))
       .serve(addr)
       .await?;

   Ok(())
}

Limitations

  • tonic_web is designed to work with grpc-web-compliant clients only. It is not expected to handle arbitrary HTTP/x.x requests or bespoke protocols.
  • Similarly, the cors support implemented by this crate will only handle grpc-web and grpc-web preflight requests.
  • Currently, grpc-web clients can only perform unary and server-streaming calls. These are the only requests this crate is designed to handle. Support for client and bi-directional streaming will be officially supported when clients do.
  • There is no support for web socket transports.

Dependencies

~7–12MB
~210K SLoC