Skip to content
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## v0.66.0 - 2025-10-21

- The `tap` function from the `function` module has been deprecated.
- `uri.query_to_string` now correctly handles `+` in query params.

## v0.65.0 - 2025-09-29

Expand Down
8 changes: 7 additions & 1 deletion src/gleam/uri.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,13 @@ pub fn query_to_string(query: List(#(String, String))) -> String {
}

fn query_pair(pair: #(String, String)) -> StringTree {
string_tree.from_strings([percent_encode(pair.0), "=", percent_encode(pair.1)])
[percent_encode_query(pair.0), "=", percent_encode_query(pair.1)]
|> string_tree.from_strings
}

fn percent_encode_query(part: String) -> String {
percent_encode(part)
|> string.replace(each: "+", with: "%2B")
}

/// Encodes a string into a percent encoded representation.
Expand Down
13 changes: 13 additions & 0 deletions test/gleam/uri_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,12 @@ pub fn query_to_string_test() {
assert query_string == "weebl%20bob=1&city=%C3%B6rebro"
}

pub fn query_to_string_special_characters_test() {
let query_string =
uri.query_to_string([#("weebl bob", "1+1-1*1.1~1!1'1(1);%")])
assert query_string == "weebl%20bob=1%2B1-1*1.1~1!1'1(1)%3B%25"
}

pub fn empty_query_to_string_test() {
let query_string = uri.query_to_string([])
assert query_string == ""
Expand Down Expand Up @@ -557,6 +563,13 @@ pub fn parse_segments_test() {
assert uri.path_segments("/weebl/../bob") == ["bob"]
}

pub fn query_to_string_parse_query_opposite_unreserved_marks_test() {
let queries = [#("weebl bob", "1+1-1*1.1~1!1'1(1);%"), #("city", "örebro")]
let query_string = uri.query_to_string(queries)
let parsed = uri.parse_query(query_string)
assert parsed == Ok(queries)
}

pub fn origin1_test() {
let assert Ok(parsed) = uri.parse("http://example.test/path?weebl#bob")
assert uri.origin(parsed) == Ok("http://example.test")
Expand Down