From e86bfe2b690914e973f72a8c206b3ca97db3c21a Mon Sep 17 00:00:00 2001 From: Kundan <281732484+ks-temporal@users.noreply.github.com> Date: Mon, 1 Jun 2026 17:27:35 -0700 Subject: [PATCH] Perform Base64 decode before JSON validation in create payloads Previously, the Base64 decoding was done after JSON validation. This prevented setting --input option with Base64 of JSON value. Base64 decoding is now done before any JSON validation, if encoding indicates json. --- .../temporalcli/commands.activity_test.go | 30 +++++++++++++++++++ internal/temporalcli/payload.go | 14 ++++----- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/internal/temporalcli/commands.activity_test.go b/internal/temporalcli/commands.activity_test.go index ec6b50a4f..2d2d680f5 100644 --- a/internal/temporalcli/commands.activity_test.go +++ b/internal/temporalcli/commands.activity_test.go @@ -2,6 +2,7 @@ package temporalcli_test import ( "context" + "encoding/base64" "encoding/json" "fmt" "strings" @@ -760,6 +761,35 @@ func (s *SharedServerSuite) TestActivity_Execute_RetriesOnEmptyPollResponse() { s.Contains(res.Stdout.String(), "standalone-result") } +func (s *SharedServerSuite) TestActivity_Execute_JsonWithBase64() { + var receivedInput any + s.Worker().OnDevActivity(func(ctx context.Context, a any) (any, error) { + receivedInput = a + return map[string]string{"foo": "bar"}, nil + }) + + jsonInput := `"my-input"` // JSON string as input, before base64 encode + base64Input := base64.StdEncoding.EncodeToString([]byte(jsonInput)) + res := s.Execute( + "activity", "execute", + "--activity-id", "exec-test", + "--type", "DevActivity", + "--task-queue", s.Worker().Options.TaskQueue, + "--start-to-close-timeout", "30s", + "-i", base64Input, + "--input-base64", + "--address", s.Address(), + ) + s.NoError(res.Err) + out := res.Stdout.String() + s.Contains(out, "Running execution:") + s.ContainsOnSameLine(out, "ActivityId", "exec-test") + s.Contains(out, "Results:") + s.ContainsOnSameLine(out, "Status", "COMPLETED") + s.ContainsOnSameLine(out, "Result", `{"foo":"bar"}`) + s.Equal("my-input", receivedInput) +} + // startActivity starts an activity via the CLI and returns // the parsed JSON response containing activityId and runId. func (s *SharedServerSuite) startActivity(activityID string, extraArgs ...string) map[string]any { diff --git a/internal/temporalcli/payload.go b/internal/temporalcli/payload.go index a2f3bc9d8..1d494f25c 100644 --- a/internal/temporalcli/payload.go +++ b/internal/temporalcli/payload.go @@ -14,6 +14,13 @@ import ( func CreatePayloads(data [][]byte, metadata map[string][][]byte, isBase64 bool) (*common.Payloads, error) { ret := &common.Payloads{Payloads: make([]*common.Payload, len(data))} for i, in := range data { + // Decode base64 if base64'd (std encoding only for now) + if isBase64 { + var err error + if in, err = base64.StdEncoding.DecodeString(string(in)); err != nil { + return nil, fmt.Errorf("input #%v is not valid base64", i+1) + } + } var metadataForIndex = make(map[string][]byte, len(metadata)) for k, vals := range metadata { if len(vals) == 0 { @@ -29,13 +36,6 @@ func CreatePayloads(data [][]byte, metadata map[string][][]byte, isBase64 bool) } metadataForIndex[k] = v } - // Decode base64 if base64'd (std encoding only for now) - if isBase64 { - var err error - if in, err = base64.StdEncoding.DecodeString(string(in)); err != nil { - return nil, fmt.Errorf("input #%v is not valid base64", i+1) - } - } ret.Payloads[i] = &common.Payload{Data: in, Metadata: metadataForIndex} } return ret, nil