From e51116c2b229e9031125161569f177e21703747a Mon Sep 17 00:00:00 2001 From: Gareth Pendleton Date: Mon, 27 Oct 2025 19:08:18 +0000 Subject: [PATCH] fix: Fix uri encoding/decoding and add new tests --- src/gluri/internal/utils.gleam | 14 +++-------- test/gluri_test.gleam | 46 +++++++++++++++------------------- 2 files changed, 23 insertions(+), 37 deletions(-) diff --git a/src/gluri/internal/utils.gleam b/src/gluri/internal/utils.gleam index 4e54d8e..1612549 100644 --- a/src/gluri/internal/utils.gleam +++ b/src/gluri/internal/utils.gleam @@ -109,7 +109,7 @@ pub fn parse_min_max( do_parse_min_max(str, "", min, max, parse_fn) } -pub fn do_parse_min_max( +fn do_parse_min_max( str: d, acc: String, min: Int, @@ -403,14 +403,6 @@ pub fn parse_hex_digits(str, min, max) { parse_min_max(str, min, max, parse_hex_digit) } -fn encoding_not_needed(i: Int) -> Bool { - // $-_.+!*'() - case i { - 36 | 45 | 95 | 46 | 43 | 33 | 42 | 39 | 40 | 41 -> True - _ -> False - } -} - fn is_unreserved_char(i: Int) -> Bool { case i { 45 | 46 | 95 | 126 -> True @@ -660,13 +652,13 @@ pub fn do_percent_encode(str: String) -> String { fn encode_codepoint(codepoint: Int) -> String { case codepoint <= 127 { True -> { - case is_unreserved_char(codepoint) || encoding_not_needed(codepoint) { + case is_unreserved_char(codepoint) { True -> { let assert Ok(cpnt) = string.utf_codepoint(codepoint) string.from_utf_codepoints([cpnt]) } False -> { - "%" <> int.to_base16(codepoint) + "%" <> string.pad_start(int.to_base16(codepoint), 2, "0") } } } diff --git a/test/gluri_test.gleam b/test/gluri_test.gleam index 3a2ad49..2157e2e 100644 --- a/test/gluri_test.gleam +++ b/test/gluri_test.gleam @@ -1146,37 +1146,31 @@ pub fn equivalence_tests() { ]) } -const percent_codec_fixtures = [ - #(" ", "%20"), - #(",", "%2C"), - #(";", "%3B"), - #(":", "%3A"), - #("!", "!"), - #("?", "%3F"), - #("'", "'"), - #("(", "("), - #(")", ")"), - #("[", "%5B"), - #("@", "%40"), - #("/", "%2F"), - #("\\", "%5C"), +const percent_encode_examples = [ + #("", ""), + #("%", "%25"), + #("%%", "%25%25"), + #(" \r\n\t\u{B}\f", "%20%0D%0A%09%0B%0C"), + #( + "-_.~0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + "-_.~0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + ), + #("\u{0}", "%00"), + #("abc\u{00}def", "abc%00def"), #("&", "%26"), - #("#", "%23"), - #("=", "%3D"), - #("~", "~"), - #("ñ", "%C3%B1"), - #("-", "-"), - #("_", "_"), - #(".", "."), - #("*", "*"), - #("+", "+"), - #("100% great+fun", "100%25%20great+fun"), + #( + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + "%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E_%60%7B%7C%7D~", + ), + #("“Aha”", "%E2%80%9CAha%E2%80%9D"), + #("\u{201C}Aha\u{201D}", "%E2%80%9CAha%E2%80%9D"), + #("*+,=>/", "%2A%2B%2C%3D%3E%2F"), ] pub fn percent_encode_tests() { describe("percent encoding", [ it("encoding", fn() { - percent_codec_fixtures + percent_encode_examples |> list.map(fn(t) { let #(a, b) = t uri.percent_encode(a) @@ -1185,7 +1179,7 @@ pub fn percent_encode_tests() { Nil }), it("decoding", fn() { - percent_codec_fixtures + percent_encode_examples |> list.map(fn(t) { let #(a, b) = t uri.percent_decode(b)