hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 36c9b5c9dbaca194d8fbd5d1358c72d325fcbfcf
parent 4a5eb434cbb25a8a23b056f5aad93e4c05677795
Author: Conrad Hoffmann <ch@bitfehler.net>
Date:   Mon, 15 Jul 2024 14:39:21 +0200

net/uri: fix absolute path when no authority

Parsing URIs without authority but with absolute path is currently
broken. If the path is just '/', the parsing fails. If the path is
longer, it will be returned without the leading slash (i.e. as relative
path). Also adds test cases for both cases to avoid future regressions.

Signed-off-by: Conrad Hoffmann <ch@bitfehler.net>

Diffstat:
Mnet/uri/+test.ha | 18++++++++++++++++++
Mnet/uri/parse.ha | 50+++++++++++++++++++++++++++++---------------------
2 files changed, 47 insertions(+), 21 deletions(-)

diff --git a/net/uri/+test.ha b/net/uri/+test.ha @@ -72,6 +72,24 @@ use net::ip; }, )!; test_uri_roundtrip( + "http:/foo/bar", + uri { + scheme = "http", + host = "", + path = "/foo/bar", + ... + }, + )!; + test_uri_roundtrip( + "http:/", + uri { + scheme = "http", + host = "", + path = "/", + ... + }, + )!; + test_uri_roundtrip( "https://sr.ht/projects?search=%23risc-v&sort=longest-active#foo", uri { scheme = "https", diff --git a/net/uri/parse.ha b/net/uri/parse.ha @@ -40,29 +40,37 @@ export fn parse(in: str) (uri | invalid) = { switch (r) { case '/' => // Either "//"+authority+path-abempty or path-absolute - switch (wantrune(&in)?) { - case '/' => - // "//" + authority + path-abempty - authority = parse_authority(&in)?; - match (strings::next(&in)) { - case let r: rune => - switch (r) { - case '?', '#' => - // path-empty - strings::prev(&in); - case '/' => - // path-absolute - strings::prev(&in); - path = parse_path(&in, - path_mode::ABSOLUTE)?; - case => - return invalid; + match (wantrune(&in)) { + case let r: rune => + switch(r) { + case '/' => + // "//" + authority + path-abempty + authority = parse_authority(&in)?; + match (strings::next(&in)) { + case let r: rune => + switch (r) { + case '?', '#' => + // path-empty + strings::prev(&in); + case '/' => + // path-absolute + strings::prev(&in); + path = parse_path(&in, + path_mode::ABSOLUTE)?; + case => + return invalid; + }; + case => void; // path-empty }; - case => void; // path-empty + case => + // path-absolute + strings::prev(&in); // return current token + strings::prev(&in); // return leading slash + path = parse_path(&in, path_mode::ABSOLUTE)?; }; - case => - // path-absolute - strings::prev(&in); + case invalid => + // path-absolute (just '/') + strings::prev(&in); // return leading slash path = parse_path(&in, path_mode::ABSOLUTE)?; }; case =>