@@ -3,7 +3,7 @@ use std::time::Duration;
3
3
use std:: { collections:: HashMap , sync:: Arc } ;
4
4
5
5
use neon:: prelude:: * ;
6
- use tonic:: metadata:: MetadataKey ;
6
+ use tonic:: metadata:: { BinaryMetadataValue , MetadataKey } ;
7
7
8
8
use temporal_sdk_core:: { ClientOptions as CoreClientOptions , CoreRuntime , RetryClient } ;
9
9
@@ -130,10 +130,16 @@ pub struct RpcCall {
130
130
pub rpc : String ,
131
131
pub req : Vec < u8 > ,
132
132
pub retry : bool ,
133
- pub metadata : HashMap < String , String > ,
133
+ pub metadata : HashMap < String , MetadataValue > ,
134
134
pub timeout : Option < Duration > ,
135
135
}
136
136
137
+ #[ derive( Debug , Clone , TryFromJs ) ]
138
+ pub enum MetadataValue {
139
+ Ascii { value : String } ,
140
+ Binary { value : Vec < u8 > } ,
141
+ }
142
+
137
143
/// Send a request to the Workflow Service using the provided Client
138
144
#[ js_function]
139
145
pub fn client_send_workflow_service_request (
@@ -584,16 +590,29 @@ fn rpc_req<P: prost::Message + Default>(call: RpcCall) -> BridgeResult<tonic::Re
584
590
585
591
let mut req = tonic:: Request :: new ( proto) ;
586
592
for ( k, v) in call. metadata {
587
- req. metadata_mut ( ) . insert (
588
- MetadataKey :: from_str ( k. as_str ( ) ) . map_err ( |err| BridgeError :: TypeError {
589
- field : None ,
590
- message : format ! ( "Invalid metadata key: {err}" ) ,
591
- } ) ?,
592
- v. parse ( ) . map_err ( |err| BridgeError :: TypeError {
593
- field : None ,
594
- message : format ! ( "Invalid metadata value: {err}" ) ,
595
- } ) ?,
596
- ) ;
593
+ match v {
594
+ MetadataValue :: Ascii { value : v } => {
595
+ req. metadata_mut ( ) . insert (
596
+ MetadataKey :: from_str ( k. as_str ( ) ) . map_err ( |err| BridgeError :: TypeError {
597
+ field : None ,
598
+ message : format ! ( "Invalid metadata key: {err}" ) ,
599
+ } ) ?,
600
+ v. parse ( ) . map_err ( |err| BridgeError :: TypeError {
601
+ field : None ,
602
+ message : format ! ( "Invalid metadata value: {err}" ) ,
603
+ } ) ?,
604
+ ) ;
605
+ }
606
+ MetadataValue :: Binary { value : v } => {
607
+ req. metadata_mut ( ) . insert_bin (
608
+ MetadataKey :: from_str ( k. as_str ( ) ) . map_err ( |err| BridgeError :: TypeError {
609
+ field : None ,
610
+ message : format ! ( "Invalid metadata key: {err}" ) ,
611
+ } ) ?,
612
+ BinaryMetadataValue :: from_bytes ( & v) ,
613
+ ) ;
614
+ }
615
+ }
597
616
}
598
617
599
618
if let Some ( timeout) = call. timeout {
@@ -628,7 +647,7 @@ mod config {
628
647
629
648
use bridge_macros:: TryFromJs ;
630
649
631
- use crate :: helpers:: * ;
650
+ use crate :: { client :: MetadataValue , helpers:: * } ;
632
651
633
652
#[ derive( Debug , Clone , TryFromJs ) ]
634
653
pub ( super ) struct ClientOptions {
@@ -637,7 +656,7 @@ mod config {
637
656
client_version : String ,
638
657
tls : Option < TlsConfig > ,
639
658
http_connect_proxy : Option < HttpConnectProxy > ,
640
- headers : Option < HashMap < String , String > > ,
659
+ headers : Option < HashMap < String , MetadataValue > > ,
641
660
api_key : Option < String > ,
642
661
disable_error_code_metric_tags : bool ,
643
662
}
@@ -677,13 +696,16 @@ mod config {
677
696
builder. tls_cfg ( tls. into ( ) ) ;
678
697
}
679
698
699
+ let ( ascii_headers, bin_headers) = partition_headers ( self . headers ) ;
700
+
680
701
let client_options = builder
681
702
. target_url ( self . target_url )
682
703
. client_name ( self . client_name )
683
704
. client_version ( self . client_version )
684
705
// tls_cfg -- above
685
706
. http_connect_proxy ( self . http_connect_proxy . map ( Into :: into) )
686
- . headers ( self . headers )
707
+ . headers ( ascii_headers)
708
+ . binary_headers ( bin_headers)
687
709
. api_key ( self . api_key )
688
710
. disable_error_code_metric_tags ( self . disable_error_code_metric_tags )
689
711
// identity -- skipped: will be set on worker
@@ -719,4 +741,32 @@ mod config {
719
741
}
720
742
}
721
743
}
744
+
745
+ fn partition_headers (
746
+ headers : Option < HashMap < String , MetadataValue > > ,
747
+ ) -> (
748
+ Option < HashMap < String , String > > ,
749
+ Option < HashMap < String , Vec < u8 > > > ,
750
+ ) {
751
+ let Some ( headers) = headers else {
752
+ return ( None , None ) ;
753
+ } ;
754
+ // Maybe with_capacity this assuming primarily ascii headers?
755
+ let mut ascii_headers = HashMap :: default ( ) ;
756
+ let mut bin_headers = HashMap :: default ( ) ;
757
+ for ( k, v) in headers {
758
+ match v {
759
+ MetadataValue :: Ascii { value : v } => {
760
+ ascii_headers. insert ( k, v) ;
761
+ }
762
+ MetadataValue :: Binary { value : v } => {
763
+ bin_headers. insert ( k, v) ;
764
+ }
765
+ }
766
+ }
767
+ (
768
+ ( !ascii_headers. is_empty ( ) ) . then_some ( ascii_headers) ,
769
+ ( !bin_headers. is_empty ( ) ) . then_some ( bin_headers) ,
770
+ )
771
+ }
722
772
}
0 commit comments