diff --git a/temporalcli/client.go b/temporalcli/client.go index d243f668f..cb75e9363 100644 --- a/temporalcli/client.go +++ b/temporalcli/client.go @@ -39,20 +39,25 @@ func (c *ClientOptions) dialClient(cctx *CommandContext) (client.Client, error) // Headers if len(c.GrpcMeta) > 0 { - headers := make(stringMapHeadersProvider, len(c.GrpcMeta)) - for _, kv := range c.GrpcMeta { - pieces := strings.SplitN(kv, "=", 2) - if len(pieces) != 2 { - return nil, fmt.Errorf("gRPC meta of %q does not have '='", kv) - } - headers[pieces[0]] = pieces[1] + headers, err := NewStringMapHeaderProvider(c.GrpcMeta) + if err != nil { + return nil, fmt.Errorf("grpc-meta %s", err) } clientOptions.HeadersProvider = headers } // Remote codec if c.CodecEndpoint != "" { - interceptor, err := payloadCodecInterceptor(c.Namespace, c.CodecEndpoint, c.CodecAuth) + codecHeaders, err := NewStringMapHeaderProvider(c.CodecHeader) + if err != nil { + return nil, fmt.Errorf("codec-header %s", err) + } + + if c.CodecAuth != "" { + codecHeaders["Authorization"] = c.CodecAuth + } + + interceptor, err := payloadCodecInterceptor(c.Namespace, c.CodecEndpoint, codecHeaders) if err != nil { return nil, fmt.Errorf("failed creating payload codec interceptor: %w", err) } @@ -145,7 +150,7 @@ func fixedHeaderOverrideInterceptor( return invoker(ctx, method, req, reply, cc, opts...) } -func payloadCodecInterceptor(namespace, codecEndpoint, codecAuth string) (grpc.UnaryClientInterceptor, error) { +func payloadCodecInterceptor(namespace, codecEndpoint string, codecHeaders stringMapHeadersProvider) (grpc.UnaryClientInterceptor, error) { codecEndpoint = strings.ReplaceAll(codecEndpoint, "{namespace}", namespace) payloadCodec := converter.NewRemotePayloadCodec( @@ -153,8 +158,8 @@ func payloadCodecInterceptor(namespace, codecEndpoint, codecAuth string) (grpc.U Endpoint: codecEndpoint, ModifyRequest: func(req *http.Request) error { req.Header.Set("X-Namespace", namespace) - if codecAuth != "" { - req.Header.Set("Authorization", codecAuth) + for headerName, headerValue := range codecHeaders { + req.Header.Set(headerName, headerValue) } return nil }, @@ -185,6 +190,18 @@ func (s stringMapHeadersProvider) GetHeaders(context.Context) (map[string]string return s, nil } +func NewStringMapHeaderProvider(config []string) (stringMapHeadersProvider, error) { + headers := make(stringMapHeadersProvider, len(config)) + for _, kv := range config { + pieces := strings.SplitN(kv, "=", 2) + if len(pieces) != 2 { + return nil, fmt.Errorf("%q does not have '='", kv) + } + headers[pieces[0]] = pieces[1] + } + return headers, nil +} + var DataConverterWithRawValue = converter.NewCompositeDataConverter( rawValuePayloadConverter{}, converter.NewNilPayloadConverter(), diff --git a/temporalcli/commands.gen.go b/temporalcli/commands.gen.go index e45623357..3ca46ec7f 100644 --- a/temporalcli/commands.gen.go +++ b/temporalcli/commands.gen.go @@ -32,6 +32,7 @@ type ClientOptions struct { TlsServerName string CodecEndpoint string CodecAuth string + CodecHeader []string } func (v *ClientOptions) buildFlags(cctx *CommandContext, f *pflag.FlagSet) { @@ -41,7 +42,7 @@ func (v *ClientOptions) buildFlags(cctx *CommandContext, f *pflag.FlagSet) { cctx.BindFlagEnvVar(f.Lookup("namespace"), "TEMPORAL_NAMESPACE") f.StringVar(&v.ApiKey, "api-key", "", "API key for request.") cctx.BindFlagEnvVar(f.Lookup("api-key"), "TEMPORAL_API_KEY") - f.StringArrayVar(&v.GrpcMeta, "grpc-meta", nil, "HTTP headers for requests. format as a `KEY=VALUE` pair May be passed multiple times to set multiple headers.") + f.StringArrayVar(&v.GrpcMeta, "grpc-meta", nil, "HTTP headers for requests. Format as a `KEY=VALUE` pair. May be passed multiple times to set multiple headers.") f.BoolVar(&v.Tls, "tls", false, "Enable base TLS encryption. Does not have additional options like mTLS or client certs.") cctx.BindFlagEnvVar(f.Lookup("tls"), "TEMPORAL_TLS") f.StringVar(&v.TlsCertPath, "tls-cert-path", "", "Path to x509 certificate. Can't be used with --tls-cert-data.") @@ -64,6 +65,7 @@ func (v *ClientOptions) buildFlags(cctx *CommandContext, f *pflag.FlagSet) { cctx.BindFlagEnvVar(f.Lookup("codec-endpoint"), "TEMPORAL_CODEC_ENDPOINT") f.StringVar(&v.CodecAuth, "codec-auth", "", "Authorization header for Codec Server requests.") cctx.BindFlagEnvVar(f.Lookup("codec-auth"), "TEMPORAL_CODEC_AUTH") + f.StringArrayVar(&v.CodecHeader, "codec-header", nil, "HTTP headers for requests to codec server. Format as a `KEY=VALUE` pair. May be passed multiple times to set multiple headers.") } type OverlapPolicyOptions struct { diff --git a/temporalcli/commandsgen/commands.yml b/temporalcli/commandsgen/commands.yml index 3df25670b..0fc735682 100644 --- a/temporalcli/commandsgen/commands.yml +++ b/temporalcli/commandsgen/commands.yml @@ -3405,7 +3405,7 @@ option-sets: type: string[] description: | HTTP headers for requests. - format as a `KEY=VALUE` pair + Format as a `KEY=VALUE` pair. May be passed multiple times to set multiple headers. - name: tls type: bool @@ -3465,6 +3465,12 @@ option-sets: type: string description: Authorization header for Codec Server requests. env: TEMPORAL_CODEC_AUTH + - name: codec-header + type: string[] + description: | + HTTP headers for requests to codec server. + Format as a `KEY=VALUE` pair. + May be passed multiple times to set multiple headers. - name: overlap-policy options: