@@ -32,6 +32,9 @@ pub use temporal_sdk_core_protos::temporal::api::{
3232 } ,
3333} ;
3434pub use tonic;
35+ use tonic:: metadata:: {
36+ AsciiMetadataKey , AsciiMetadataValue , BinaryMetadataKey , BinaryMetadataValue ,
37+ } ;
3538pub use worker_registry:: { Slot , SlotManager , SlotProvider , WorkerKey } ;
3639pub use workflow_handle:: {
3740 GetWorkflowResultOpts , WorkflowExecutionInfo , WorkflowExecutionResult , WorkflowHandle ,
@@ -149,6 +152,13 @@ pub struct ClientOptions {
149152 #[ builder( default ) ]
150153 pub headers : Option < HashMap < String , String > > ,
151154
155+ /// HTTP headers to include on every RPC call as binary gRPC metadata (typically encoded as
156+ /// base64).
157+ ///
158+ /// These must be valid binary gRPC metadata keys (and end with a `-bin` suffix).
159+ #[ builder( default ) ]
160+ pub binary_headers : Option < HashMap < String , Vec < u8 > > > ,
161+
152162 /// API key which is set as the "Authorization" header with "Bearer " prepended. This will only
153163 /// be applied if the headers don't already have an "Authorization" header.
154164 #[ builder( default ) ]
@@ -344,11 +354,20 @@ pub struct ConfiguredClient<C> {
344354}
345355
346356impl < C > ConfiguredClient < C > {
347- /// Set HTTP request headers overwriting previous headers
357+ /// Set HTTP request headers overwriting previous headers.
358+ ///
359+ /// This will not affect headers set via [ClientOptions::binary_headers].
348360 pub fn set_headers ( & self , headers : HashMap < String , String > ) {
349361 self . headers . write ( ) . user_headers = headers;
350362 }
351363
364+ /// Set binary HTTP request headers overwriting previous headers.
365+ ///
366+ /// This will not affect headers set via [ClientOptions::headers].
367+ pub fn set_binary_headers ( & self , binary_headers : HashMap < String , Vec < u8 > > ) {
368+ self . headers . write ( ) . user_binary_headers = binary_headers;
369+ }
370+
352371 /// Set API key, overwriting previous
353372 pub fn set_api_key ( & self , api_key : Option < String > ) {
354373 self . headers . write ( ) . api_key = api_key;
@@ -374,6 +393,7 @@ impl<C> ConfiguredClient<C> {
374393#[ derive( Debug ) ]
375394struct ClientHeaders {
376395 user_headers : HashMap < String , String > ,
396+ user_binary_headers : HashMap < String , Vec < u8 > > ,
377397 api_key : Option < String > ,
378398}
379399
@@ -383,11 +403,23 @@ impl ClientHeaders {
383403 // Only if not already present
384404 if !metadata. contains_key ( key) {
385405 // Ignore invalid keys/values
386- if let ( Ok ( key) , Ok ( val) ) = ( MetadataKey :: from_str ( key) , val. parse ( ) ) {
406+ if let ( Ok ( key) , Ok ( val) ) = (
407+ AsciiMetadataKey :: from_str ( key) ,
408+ AsciiMetadataValue :: from_str ( val) ,
409+ ) {
387410 metadata. insert ( key, val) ;
388411 }
389412 }
390413 }
414+ for ( key, val) in self . user_binary_headers . iter ( ) {
415+ // Only if not already present
416+ if !metadata. contains_key ( key) {
417+ // Ignore invalid keys
418+ if let Ok ( key) = BinaryMetadataKey :: from_str ( key) {
419+ metadata. insert_bin ( key, BinaryMetadataValue :: from_bytes ( val) ) ;
420+ }
421+ }
422+ }
391423 if let Some ( api_key) = & self . api_key {
392424 // Only if not already present
393425 if !metadata. contains_key ( "authorization" )
@@ -492,6 +524,7 @@ impl ClientOptions {
492524
493525 let headers = Arc :: new ( RwLock :: new ( ClientHeaders {
494526 user_headers : self . headers . clone ( ) . unwrap_or_default ( ) ,
527+ user_binary_headers : self . binary_headers . clone ( ) . unwrap_or_default ( ) ,
495528 api_key : self . api_key . clone ( ) ,
496529 } ) ) ;
497530 let interceptor = ServiceCallInterceptor {
@@ -1770,6 +1803,7 @@ mod tests {
17701803 // Initial header set
17711804 let headers = Arc :: new ( RwLock :: new ( ClientHeaders {
17721805 user_headers : HashMap :: new ( ) ,
1806+ user_binary_headers : HashMap :: new ( ) ,
17731807 api_key : Some ( "my-api-key" . to_owned ( ) ) ,
17741808 } ) ) ;
17751809 headers
0 commit comments