From c753711d86fda7392c2556741de0fd9b70d7c2e1 Mon Sep 17 00:00:00 2001 From: blob1807 <12388588+blob1807@users.noreply.github.com> Date: Sat, 13 Apr 2024 00:39:32 +1000 Subject: [PATCH 1/4] Added support for URL fragments Added support for a URL's fragment/anchor to `split_url` & `join_url` in `core:net` plus 4 new tests to cover it. --- core/net/url.odin | 17 +++++- tests/core/net/test_core_net.odin | 86 +++++++++++++++++++++++-------- 2 files changed, 80 insertions(+), 23 deletions(-) diff --git a/core/net/url.odin b/core/net/url.odin index 7ad88bd1f..5257b757c 100644 --- a/core/net/url.odin +++ b/core/net/url.odin @@ -21,7 +21,7 @@ import "core:strconv" import "core:unicode/utf8" import "core:encoding/hex" -split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host, path: string, queries: map[string]string) { +split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host, path: string, queries: map[string]string, fragment: string) { s := url i := strings.index(s, "://") @@ -30,6 +30,12 @@ split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host, s = s[i+3:] } + i = strings.index_byte(s, '#') + if i != -1 { + fragment = s[i+1:] + s = s[:i] + } + i = strings.index(s, "?") if i != -1 { query_str := s[i+1:] @@ -62,7 +68,7 @@ split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host, return } -join_url :: proc(scheme, host, path: string, queries: map[string]string, allocator := context.allocator) -> string { +join_url :: proc(scheme, host, path: string, queries: map[string]string, fragment: string, allocator := context.allocator) -> string { b := strings.builder_make(allocator) strings.builder_grow(&b, len(scheme) + 3 + len(host) + 1 + len(path)) @@ -95,6 +101,13 @@ join_url :: proc(scheme, host, path: string, queries: map[string]string, allocat i += 1 } + if fragment != "" { + if fragment[0] != '#' { + strings.write_byte(&b, '#') + } + strings.write_string(&b, strings.trim_space(fragment)) + } + return strings.to_string(b) } diff --git a/tests/core/net/test_core_net.odin b/tests/core/net/test_core_net.odin index 579298904..2a581c66b 100644 --- a/tests/core/net/test_core_net.odin +++ b/tests/core/net/test_core_net.odin @@ -473,6 +473,7 @@ client_sends_server_data :: proc(t: ^testing.T) { URL_Test :: struct { scheme, host, path: string, queries: map[string]string, + fragment: string, url: []string, } @@ -481,58 +482,78 @@ split_url_test :: proc(t: ^testing.T) { test_cases := []URL_Test{ { "http", "example.com", "/", - {}, + {}, "", {"http://example.com"}, }, { "https", "odin-lang.org", "/", - {}, + {}, "", {"https://odin-lang.org"}, }, { "https", "odin-lang.org", "/docs/", - {}, + {}, "", {"https://odin-lang.org/docs/"}, }, { "https", "odin-lang.org", "/docs/overview", - {}, + {}, "", {"https://odin-lang.org/docs/overview"}, }, { "http", "example.com", "/", - {"a" = "b"}, + {"a" = "b"}, "", {"http://example.com?a=b"}, }, { "http", "example.com", "/", - {"a" = ""}, + {"a" = ""}, "", {"http://example.com?a"}, }, { "http", "example.com", "/", - {"a" = "b", "c" = "d"}, + {"a" = "b", "c" = "d"}, "", {"http://example.com?a=b&c=d"}, }, { "http", "example.com", "/", - {"a" = "", "c" = "d"}, + {"a" = "", "c" = "d"}, "", {"http://example.com?a&c=d"}, }, { "http", "example.com", "/example", - {"a" = "", "b" = ""}, + {"a" = "", "b" = ""}, "", {"http://example.com/example?a&b"}, }, { "https", "example.com", "/callback", - {"redirect" = "https://other.com/login"}, + {"redirect" = "https://other.com/login"}, "", {"https://example.com/callback?redirect=https://other.com/login"}, }, + { + "http", "odin-lang.org", "/", + {}, "Hellope", + {"http://odin-lang.org#Hellope"} + }, + { + "https", "odin-lang.org", "/", + {"a" = ""}, "Hellope", + {"https://odin-lang.org?a#Hellope"} + }, + { + "http", "example.com", "/", + {"a" = "b"}, "Hellope", + {"http://example.com?a=b#Hellope"} + }, + { + "https", "example.com", "/example", + {}, "Hellope", + {"https://example.com/example#Hellope"} + }, } for test in test_cases { - scheme, host, path, queries := net.split_url(test.url[0]) + scheme, host, path, queries, fragment := net.split_url(test.url[0]) defer { delete(queries) delete(test.queries) @@ -551,6 +572,9 @@ split_url_test :: proc(t: ^testing.T) { msg = fmt.tprintf("Expected `net.split_url` to return %s, got %s", expected, v) expect(t, v == expected, msg) } + msg = fmt.tprintf("Expected `net.split_url` to return %s, got %s", test.fragment, fragment) + expect(t, fragment == test.fragment, msg) + } } @@ -560,53 +584,73 @@ join_url_test :: proc(t: ^testing.T) { test_cases := []URL_Test{ { "http", "example.com", "/", - {}, + {}, "", {"http://example.com/"}, }, { "https", "odin-lang.org", "/", - {}, + {}, "", {"https://odin-lang.org/"}, }, { "https", "odin-lang.org", "/docs/", - {}, + {}, "", {"https://odin-lang.org/docs/"}, }, { "https", "odin-lang.org", "/docs/overview", - {}, + {}, "", {"https://odin-lang.org/docs/overview"}, }, { "http", "example.com", "/", - {"a" = "b"}, + {"a" = "b"}, "", {"http://example.com/?a=b"}, }, { "http", "example.com", "/", - {"a" = ""}, + {"a" = ""}, "", {"http://example.com/?a"}, }, { "http", "example.com", "/", - {"a" = "b", "c" = "d"}, + {"a" = "b", "c" = "d"}, "", {"http://example.com/?a=b&c=d", "http://example.com/?c=d&a=b"}, }, { "http", "example.com", "/", - {"a" = "", "c" = "d"}, + {"a" = "", "c" = "d"}, "", {"http://example.com/?a&c=d", "http://example.com/?c=d&a"}, }, { "http", "example.com", "/example", - {"a" = "", "b" = ""}, + {"a" = "", "b" = ""}, "", {"http://example.com/example?a&b", "http://example.com/example?b&a"}, }, + { + "http", "odin-lang.org", "", + {}, "Hellope", + {"http://odin-lang.org#Hellope"} + }, + { + "https", "odin-lang.org", "", + {"a" = ""}, "Hellope", + {"https://odin-lang.org?a#Hellope"} + }, + { + "http", "example.com", "", + {"a" = "b"}, "Hellope", + {"http://example.com?a=b#Hellope"} + }, + { + "https", "example.com", "/example", + {}, "Hellope", + {"https://example.com/example#Hellope"} + }, } for test in test_cases { - url := net.join_url(test.scheme, test.host, test.path, test.queries) + url := net.join_url(test.scheme, test.host, test.path, test.queries, test.fragment) defer { delete(url) delete(test.queries) From 2d1260bec9874907fd6545bfbabc0829c697b361 Mon Sep 17 00:00:00 2001 From: blob1807 <12388588+blob1807@users.noreply.github.com> Date: Sat, 13 Apr 2024 00:47:49 +1000 Subject: [PATCH 2/4] uniformity change small change to check things uniform --- core/net/url.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/net/url.odin b/core/net/url.odin index 5257b757c..16aa57ec5 100644 --- a/core/net/url.odin +++ b/core/net/url.odin @@ -30,7 +30,7 @@ split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host, s = s[i+3:] } - i = strings.index_byte(s, '#') + i = strings.index(s, "#") if i != -1 { fragment = s[i+1:] s = s[:i] @@ -103,7 +103,7 @@ join_url :: proc(scheme, host, path: string, queries: map[string]string, fragmen if fragment != "" { if fragment[0] != '#' { - strings.write_byte(&b, '#') + strings.write_string(&b, "#") } strings.write_string(&b, strings.trim_space(fragment)) } From 6348b56c8bfced2fc202517a322bbf9505725384 Mon Sep 17 00:00:00 2001 From: blob1807 <12388588+blob1807@users.noreply.github.com> Date: Sat, 13 Apr 2024 00:57:36 +1000 Subject: [PATCH 3/4] Move rounded tests --- tests/core/net/test_core_net.odin | 34 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/core/net/test_core_net.odin b/tests/core/net/test_core_net.odin index 2a581c66b..52d22a9f0 100644 --- a/tests/core/net/test_core_net.odin +++ b/tests/core/net/test_core_net.odin @@ -531,9 +531,9 @@ split_url_test :: proc(t: ^testing.T) { {"https://example.com/callback?redirect=https://other.com/login"}, }, { - "http", "odin-lang.org", "/", + "http", "example.com", "/", {}, "Hellope", - {"http://odin-lang.org#Hellope"} + {"http://example.com#Hellope"} }, { "https", "odin-lang.org", "/", @@ -542,13 +542,13 @@ split_url_test :: proc(t: ^testing.T) { }, { "http", "example.com", "/", - {"a" = "b"}, "Hellope", - {"http://example.com?a=b#Hellope"} + {"a" = "b"}, "BeesKnees", + {"http://example.com?a=b#BeesKnees"} }, { - "https", "example.com", "/example", - {}, "Hellope", - {"https://example.com/example#Hellope"} + "https", "odin-lang.org", "/docs/overview/", + {}, "hellope", + {"https://odin-lang.org/docs/overview/#hellope"} }, } @@ -628,24 +628,24 @@ join_url_test :: proc(t: ^testing.T) { {"http://example.com/example?a&b", "http://example.com/example?b&a"}, }, { - "http", "odin-lang.org", "", + "http", "example.com", "/", {}, "Hellope", - {"http://odin-lang.org#Hellope"} + {"http://example.com/#Hellope"} }, { - "https", "odin-lang.org", "", + "https", "odin-lang.org", "/", {"a" = ""}, "Hellope", - {"https://odin-lang.org?a#Hellope"} + {"https://odin-lang.org/?a#Hellope"} }, { - "http", "example.com", "", - {"a" = "b"}, "Hellope", - {"http://example.com?a=b#Hellope"} + "http", "example.com", "/", + {"a" = "b"}, "BeesKnees", + {"http://example.com/?a=b#BeesKnees"} }, { - "https", "example.com", "/example", - {}, "Hellope", - {"https://example.com/example#Hellope"} + "https", "odin-lang.org", "/docs/overview/", + {}, "hellope", + {"https://odin-lang.org/docs/overview/#hellope"} }, } From a4d16e97a1c48481ff6cda5c7541a552f1e6d9e8 Mon Sep 17 00:00:00 2001 From: blob1807 <12388588+blob1807@users.noreply.github.com> Date: Sat, 13 Apr 2024 01:14:55 +1000 Subject: [PATCH 4/4] Fix CI's parser --- tests/core/net/test_core_net.odin | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/core/net/test_core_net.odin b/tests/core/net/test_core_net.odin index 52d22a9f0..9df03414c 100644 --- a/tests/core/net/test_core_net.odin +++ b/tests/core/net/test_core_net.odin @@ -533,22 +533,22 @@ split_url_test :: proc(t: ^testing.T) { { "http", "example.com", "/", {}, "Hellope", - {"http://example.com#Hellope"} + {"http://example.com#Hellope"}, }, { "https", "odin-lang.org", "/", {"a" = ""}, "Hellope", - {"https://odin-lang.org?a#Hellope"} + {"https://odin-lang.org?a#Hellope"}, }, { "http", "example.com", "/", {"a" = "b"}, "BeesKnees", - {"http://example.com?a=b#BeesKnees"} + {"http://example.com?a=b#BeesKnees"}, }, { "https", "odin-lang.org", "/docs/overview/", {}, "hellope", - {"https://odin-lang.org/docs/overview/#hellope"} + {"https://odin-lang.org/docs/overview/#hellope"}, }, } @@ -630,22 +630,22 @@ join_url_test :: proc(t: ^testing.T) { { "http", "example.com", "/", {}, "Hellope", - {"http://example.com/#Hellope"} + {"http://example.com/#Hellope"}, }, { "https", "odin-lang.org", "/", {"a" = ""}, "Hellope", - {"https://odin-lang.org/?a#Hellope"} + {"https://odin-lang.org/?a#Hellope"}, }, { "http", "example.com", "/", {"a" = "b"}, "BeesKnees", - {"http://example.com/?a=b#BeesKnees"} + {"http://example.com/?a=b#BeesKnees"}, }, { "https", "odin-lang.org", "/docs/overview/", {}, "hellope", - {"https://odin-lang.org/docs/overview/#hellope"} + {"https://odin-lang.org/docs/overview/#hellope"}, }, }