From 66b689cb11031bfb130ee9179bdd24c518e033b6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 4 Jul 2026 03:37:02 +0000 Subject: [PATCH 1/2] Fix toParam to encode byte[] as base64 instead of calling ToString() Previously, passing a byte[] to toParam fell through to the obj.ToString() fallback, producing the string "System.Byte[]" instead of a valid base64 representation. This fix adds an explicit arm before the fallthrough that calls Convert.ToBase64String, consistent with how toQueryParams already handles byte[] values. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/SwaggerProvider.Runtime/RuntimeHelpers.fs | 6 +++ .../RuntimeHelpersTests.fs | 43 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/src/SwaggerProvider.Runtime/RuntimeHelpers.fs b/src/SwaggerProvider.Runtime/RuntimeHelpers.fs index c7f07e3a..950dcbeb 100644 --- a/src/SwaggerProvider.Runtime/RuntimeHelpers.fs +++ b/src/SwaggerProvider.Runtime/RuntimeHelpers.fs @@ -222,6 +222,12 @@ module RuntimeHelpers = | :? float32 as f -> f.ToString() | :? double as d -> d.ToString() | :? Guid as g -> g.ToString() + // Byte arrays are encoded as base64 — the OpenAPI "byte" format (RFC 4648). + // Without this arm, byte[] falls through to obj.ToString() → "System.Byte[]", + // which is incorrect for path, header, cookie, and form-urlencoded parameters. + // Note: toQueryParams has its own byte[]/Option arms that use + // client.Serialize; this arm aligns with that behaviour for all other contexts. + | :? array as xs -> Convert.ToBase64String xs | _ -> // Hoist GetType() once; previously tryFormatDateOnly and tryFormatTimeOnly // each called GetType() internally, resulting in up to 3 GetType() calls for diff --git a/tests/SwaggerProvider.Tests/RuntimeHelpersTests.fs b/tests/SwaggerProvider.Tests/RuntimeHelpersTests.fs index 14ed60c0..0b533f7e 100644 --- a/tests/SwaggerProvider.Tests/RuntimeHelpersTests.fs +++ b/tests/SwaggerProvider.Tests/RuntimeHelpersTests.fs @@ -142,6 +142,32 @@ module ToParamTests = let result = toParam(box(None: TimeOnly option)) result |> shouldEqual null + [] + let ``toParam encodes byte array as base64 (OpenAPI 'byte' format)``() = + // Without the byte[] arm, obj.ToString() would yield "System.Byte[]". + // The correct encoding for the OpenAPI "byte" format is standard base64. + let bytes = [| 1uy; 2uy; 3uy |] + let result = toParam(box bytes) + result |> shouldEqual(Convert.ToBase64String bytes) + + [] + let ``toParam encodes empty byte array as empty base64 string``() = + let result = toParam(box([||]: byte[])) + result |> shouldEqual "" + + [] + let ``toParam unwraps Some(byte array) and encodes as base64``() = + // Option Some is unwrapped by the generic option arm, then toParam + // is called recursively on the inner byte[] value. + let bytes = [| 72uy; 101uy; 108uy; 108uy; 111uy |] // "Hello" in ASCII + let result = toParam(box(Some bytes)) + result |> shouldEqual(Convert.ToBase64String bytes) + + [] + let ``toParam returns null for None(byte array)``() = + let result = toParam(box(None: byte[] option)) + result |> shouldEqual null + // ── CLI enum serialization via toParam ────────────────────────────────────────────────────── // toParam must serialize string enums to their original OpenAPI wire values and integer @@ -1292,6 +1318,23 @@ module ToFormUrlEncodedContentTests = body |> shouldNotContainText "nestedNone" } + [] + let ``toFormUrlEncodedContent encodes byte array as base64``() = + // Without the byte[] arm in toParam, this produced "data=System.Byte%5B%5D". + // With the fix, byte arrays are encoded as standard base64 (OpenAPI 'byte' format). + task { + let bytes = [| 1uy; 2uy; 3uy |] + let expected = Convert.ToBase64String bytes + + use content = toFormUrlEncodedContent(seq { ("data", box bytes) }) + + let! body = content.ReadAsStringAsync() + let encodedValue = body.Substring("data=".Length) + let decodedValue = WebUtility.UrlDecode(encodedValue) + + decodedValue |> shouldEqual expected + } + module ToMultipartFormDataContentTests = From 13c47dc731a55ee5567d77db555099e4ed7a2f99 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 4 Jul 2026 03:37:04 +0000 Subject: [PATCH 2/2] ci: trigger checks