Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add codec-header config (closes #753) #755

Merged
merged 3 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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