16 releases (8 breaking)

0.12.3 Sep 26, 2024
0.12.1 Jul 17, 2024
0.11.0 Feb 8, 2024
0.10.2 Sep 28, 2023
0.1.0 Jul 8, 2021

#1830 in Network programming

Download history 32432/week @ 2024-08-21 33531/week @ 2024-08-28 43035/week @ 2024-09-04 33169/week @ 2024-09-11 37742/week @ 2024-09-18 41353/week @ 2024-09-25 44278/week @ 2024-10-02 31463/week @ 2024-10-09 42332/week @ 2024-10-16 34859/week @ 2024-10-23 38930/week @ 2024-10-30 21877/week @ 2024-11-06 96173/week @ 2024-11-13 53157/week @ 2024-11-20 39357/week @ 2024-11-27 47791/week @ 2024-12-04

241,329 downloads per month
Used in 41 crates (27 directly)

MIT license

1MB
11K 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)
       .layer(GrpcWebLayer::new())
       .add_service(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.

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.

#[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)
       // This will apply the gRPC-Web translation layer
       .layer(GrpcWebLayer::new())
       .add_service(greeter)
       .serve(addr)
       .await?;

   Ok(())
}

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

~5–11MB
~116K SLoC