Skip to content

Commit

Permalink
Add codec-header config (closes #753) (#755)
Browse files Browse the repository at this point in the history
  • Loading branch information
EddieWhi authored Feb 14, 2025
1 parent df49911 commit 2467e7d
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 13 deletions.
39 changes: 28 additions & 11 deletions temporalcli/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -145,16 +150,16 @@ 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(
converter.RemotePayloadCodecOptions{
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
},
Expand Down Expand Up @@ -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(),
Expand Down
4 changes: 3 additions & 1 deletion temporalcli/commands.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type ClientOptions struct {
TlsServerName string
CodecEndpoint string
CodecAuth string
CodecHeader []string
}

func (v *ClientOptions) buildFlags(cctx *CommandContext, f *pflag.FlagSet) {
Expand All @@ -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.")
Expand All @@ -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 {
Expand Down
8 changes: 7 additions & 1 deletion temporalcli/commandsgen/commands.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 2467e7d

Please sign in to comment.