9797#![ doc( html_root_url = "https://docs.rs/tonic-web/0.9.1" ) ]
9898#![ doc( issue_tracker_base_url = "https://github.com/hyperium/tonic/issues/" ) ]
9999
100+ use bytes:: Buf ;
101+ use http_body:: Body ;
100102pub use layer:: GrpcWebLayer ;
101103pub use service:: { GrpcWebService , ResponseFuture } ;
102104
@@ -106,8 +108,11 @@ mod service;
106108
107109use http:: header:: HeaderName ;
108110use std:: time:: Duration ;
109- use tonic:: { body:: BoxBody , server:: NamedService } ;
110- use tower_http:: cors:: { AllowOrigin , CorsLayer } ;
111+ use tonic:: { body:: BoxBody , server:: NamedService , Status } ;
112+ use tower_http:: {
113+ cors:: { AllowOrigin , CorsLayer } ,
114+ BoxError ,
115+ } ;
111116use tower_layer:: Layer ;
112117use tower_service:: Service ;
113118
@@ -117,17 +122,16 @@ const DEFAULT_EXPOSED_HEADERS: [&str; 3] =
117122const DEFAULT_ALLOW_HEADERS : [ & str ; 4 ] =
118123 [ "x-grpc-web" , "content-type" , "x-user-agent" , "grpc-timeout" ] ;
119124
120- type BoxError = Box < dyn std:: error:: Error + Send + Sync > ;
121-
122125/// Enable a tonic service to handle grpc-web requests with the default configuration.
123126///
124127/// You can customize the CORS configuration composing the [`GrpcWebLayer`] with the cors layer of your choice.
125- pub fn enable < S > ( service : S ) -> CorsGrpcWeb < S >
128+ pub fn enable < S , RespBody > ( service : S ) -> CorsGrpcWeb < S , RespBody >
126129where
127- S : Service < http:: Request < hyper :: Body > , Response = http:: Response < BoxBody > > ,
130+ S : Service < http:: Request < BoxBody > , Response = http:: Response < RespBody > > ,
128131 S : Clone + Send + ' static ,
129132 S :: Future : Send + ' static ,
130133 S :: Error : Into < BoxError > + Send ,
134+ RespBody : Body ,
131135{
132136 let cors = CorsLayer :: new ( )
133137 . allow_origin ( AllowOrigin :: mirror_request ( ) )
@@ -153,34 +157,52 @@ where
153157
154158/// A newtype wrapper around [`GrpcWebLayer`] and [`tower_http::cors::CorsLayer`] to allow
155159/// `tonic_web::enable` to implement the [`NamedService`] trait.
156- #[ derive( Debug , Clone ) ]
157- pub struct CorsGrpcWeb < S > ( tower_http:: cors:: Cors < GrpcWebService < S > > ) ;
160+ #[ derive( Debug ) ]
161+ pub struct CorsGrpcWeb < S , RespBody > ( tower_http:: cors:: Cors < GrpcWebService < S , RespBody > > ) ;
162+
163+ impl < S : Clone , RespBody > Clone for CorsGrpcWeb < S , RespBody > {
164+ fn clone ( & self ) -> Self {
165+ Self ( self . 0 . clone ( ) )
166+ }
167+ }
158168
159- impl < S > Service < http:: Request < hyper :: Body > > for CorsGrpcWeb < S >
169+ impl < S , ReqBody , RespBody > Service < http:: Request < ReqBody > > for CorsGrpcWeb < S , RespBody >
160170where
161- S : Service < http:: Request < hyper :: Body > , Response = http:: Response < BoxBody > > ,
171+ S : Service < http:: Request < BoxBody > , Response = http:: Response < RespBody > > ,
162172 S : Clone + Send + ' static ,
163173 S :: Future : Send + ' static ,
164174 S :: Error : Into < BoxError > + Send ,
175+ ReqBody : Body + Send + ' static ,
176+ ReqBody :: Error : Into < BoxError > + Send ,
177+ RespBody : Body + Default + Send + ' static ,
178+ RespBody :: Error : Into < BoxError > + Send + ' static ,
165179{
166- type Response = S :: Response ;
167- type Error = S :: Error ;
168- type Future =
169- <tower_http:: cors:: Cors < GrpcWebService < S > > as Service < http:: Request < hyper:: Body > > >:: Future ;
180+ type Response = <tower_http:: cors:: Cors < GrpcWebService < S , RespBody > > as Service <
181+ http:: Request < ReqBody > ,
182+ > >:: Response ;
183+ type Error = <tower_http:: cors:: Cors < GrpcWebService < S , RespBody > > as Service <
184+ http:: Request < ReqBody > ,
185+ > >:: Error ;
186+ type Future = <tower_http:: cors:: Cors < GrpcWebService < S , RespBody > > as Service <
187+ http:: Request < ReqBody > ,
188+ > >:: Future ;
170189
171190 fn poll_ready (
172191 & mut self ,
173192 cx : & mut std:: task:: Context < ' _ > ,
174193 ) -> std:: task:: Poll < Result < ( ) , Self :: Error > > {
175- self . 0 . poll_ready ( cx)
194+ <tower_http:: cors:: Cors < GrpcWebService < S , RespBody > > as Service < http:: Request < ReqBody > > >:: poll_ready (
195+ & mut self . 0 ,
196+ cx,
197+ )
176198 }
177199
178- fn call ( & mut self , req : http:: Request < hyper :: Body > ) -> Self :: Future {
200+ fn call ( & mut self , req : http:: Request < ReqBody > ) -> Self :: Future {
179201 self . 0 . call ( req)
180202 }
181203}
182204
183- impl < S > NamedService for CorsGrpcWeb < S >
205+ impl < S , RespBody > NamedService for CorsGrpcWeb < S , RespBody >
184206where
185207 S : NamedService ,
186208{
@@ -205,3 +227,12 @@ pub(crate) mod util {
205227 ) ;
206228 }
207229}
230+
231+ pub ( crate ) fn box_body < D : Buf , E : Into < BoxError > + Send > (
232+ body : impl Body < Data = D , Error = E > + Send + ' static ,
233+ ) -> BoxBody {
234+ let bod = body
235+ . map_data ( |mut d| d. copy_to_bytes ( d. remaining ( ) ) )
236+ . map_err ( |e| Status :: from_error ( e. into ( ) as BoxError ) ) ;
237+ bod. boxed_unsync ( )
238+ }
0 commit comments