tonic_web_arcanyx_fork/
lib.rs

1//! grpc-web protocol translation for [`tonic`] services.
2//!
3//! [`tonic_web`] enables tonic servers to handle requests from [grpc-web] clients directly,
4//! without the need of an external proxy. It achieves this by wrapping individual tonic services
5//! with a [tower] service that performs the translation between protocols and handles `cors`
6//! requests.
7//!
8//! ## Getting Started
9//!
10//! ```toml
11//! [dependencies]
12//! tonic_web = "0.1"
13//! ```
14//!
15//! ## Enabling tonic services
16//!
17//! The easiest way to get started, is to call the [`enable`] function with your tonic service
18//! and allow the tonic server to accept HTTP/1.1 requests:
19//!
20//! ```ignore
21//! #[tokio::main]
22//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
23//!     let addr = "[::1]:50051".parse().unwrap();
24//!     let greeter = GreeterServer::new(MyGreeter::default());
25//!
26//!     Server::builder()
27//!        .accept_http1(true)
28//!        .add_service(tonic_web::enable(greeter))
29//!        .serve(addr)
30//!        .await?;
31//!
32//!    Ok(())
33//! }
34//!
35//! ```
36//! This will apply a default configuration that works well with grpc-web clients out of the box.
37//! See the [`Config`] documentation for details.
38//!
39//! Alternatively, if you have a tls enabled server, you could skip setting `accept_http1` to `true`.
40//! This works because the browser will handle `ALPN`.
41//!
42//! ```ignore
43//! #[tokio::main]
44//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
45//!     let cert = tokio::fs::read("server.pem").await?;
46//!     let key = tokio::fs::read("server.key").await?;
47//!     let identity = Identity::from_pem(cert, key);
48//!
49//!     let addr = "[::1]:50051".parse().unwrap();
50//!     let greeter = GreeterServer::new(MyGreeter::default());
51//!
52//!     // No need to enable HTTP/1
53//!     Server::builder()
54//!        .tls_config(ServerTlsConfig::new().identity(identity))?
55//!        .add_service(tonic_web::enable(greeter))
56//!        .serve(addr)
57//!        .await?;
58//!
59//!    Ok(())
60//! }
61//! ```
62//!
63//! ## Limitations
64//!
65//! * `tonic_web` is designed to work with grpc-web-compliant clients only. It is not expected to
66//! handle arbitrary HTTP/x.x requests or bespoke protocols.
67//! * Similarly, the cors support implemented  by this crate will *only* handle grpc-web and
68//! grpc-web preflight requests.
69//! * Currently, grpc-web clients can only perform `unary` and `server-streaming` calls. These
70//! are the only requests this crate is designed to handle. Support for client and bi-directional
71//! streaming will be officially supported when clients do.
72//! * There is no support for web socket transports.
73//!
74//!
75//! [`tonic`]: https://github.com/hyperium/tonic
76//! [`tonic_web`]: https://github.com/hyperium/tonic
77//! [grpc-web]: https://github.com/grpc/grpc-web
78//! [tower]: https://github.com/tower-rs/tower
79//! [`enable`]: crate::enable()
80//! [`Config`]: crate::Config
81#![warn(
82    missing_debug_implementations,
83    missing_docs,
84    rust_2018_idioms,
85    unreachable_pub
86)]
87#![doc(html_root_url = "https://docs.rs/tonic-web/0.4.0")]
88#![doc(issue_tracker_base_url = "https://github.com/hyperium/tonic/issues/")]
89
90pub use config::Config;
91
92mod call;
93mod config;
94mod cors;
95mod service;
96
97use crate::service::GrpcWeb;
98use std::future::Future;
99use std::pin::Pin;
100use tonic::body::BoxBody;
101use tonic::transport::NamedService;
102use tower_service::Service;
103
104/// enable a tonic service to handle grpc-web requests with the default configuration.
105///
106/// Shortcut for `tonic_web::config().enable(service)`
107pub fn enable<S>(service: S) -> GrpcWeb<S>
108where
109    S: Service<http::Request<hyper::Body>, Response = http::Response<BoxBody>>,
110    S: NamedService + Clone + Send + 'static,
111    S::Future: Send + 'static,
112    S::Error: Into<BoxError> + Send,
113{
114    config().enable(service)
115}
116
117/// returns a default [`Config`] instance for configuring services.
118///
119/// ## Example
120///
121/// ```
122/// let config = tonic_web::config()
123///      .allow_origins(vec!["http://foo.com"])
124///      .allow_credentials(false)
125///      .expose_headers(vec!["x-request-id"]);
126///
127/// // let greeter = config.enable(Greeter);
128/// // let route_guide = config.enable(RouteGuide);
129/// ```
130pub fn config() -> Config {
131    Config::default()
132}
133
134type BoxError = Box<dyn std::error::Error + Send + Sync>;
135type BoxFuture<T, E> = Pin<Box<dyn Future<Output = Result<T, E>> + Send>>;