diff options
Diffstat (limited to '')
-rw-r--r-- | NOTES.md | 306 |
1 files changed, 306 insertions, 0 deletions
@@ -7,3 +7,309 @@ You will need the following dependencies: [various patches](https://lists.sr.ht/~sircmpwn/hare-dev/patches?search=from%3Arunxiyu+prefix%3Ahare-http) - [hare-htmpl](https://forge.runxiyu.org/hare/:/repos/hare-htmpl/) ([backup](https://git.sr.ht/~runxiyu/hare-htmpl)) + + +Also, you'll need various horrible patches for `net::uri` before that gets fixed: + +``` +diff --git a/net/uri/+test.ha b/net/uri/+test.ha +index 345f41ee..63272d52 100644 +--- a/net/uri/+test.ha ++++ b/net/uri/+test.ha +@@ -10,7 +10,7 @@ use net::ip; + uri { + scheme = "file", + host = "", +- path = "/my/path/to/file", ++ raw_path = "/my/path/to/file", + ... + }, + )!; +@@ -19,7 +19,7 @@ use net::ip; + uri { + scheme = "http", + host = "harelang.org", +- path = "/", ++ raw_path = "/", + ... + }, + )!; +@@ -38,7 +38,7 @@ use net::ip; + scheme = "ldap", + host = [13, 37, 73, 31]: ip::addr4, + port = 1234, +- path = "/", ++ raw_path = "/", + ... + }, + )!; +@@ -47,7 +47,7 @@ use net::ip; + uri { + scheme = "http", + host = ip::parse("::1")!, +- path = "/test", ++ raw_path = "/test", + ... + }, + )!; +@@ -58,7 +58,7 @@ use net::ip; + uri { + scheme = "urn", + host = "", +- path = "example:animal:ferret:nose", ++ raw_path = "example:animal:ferret:nose", + ... + }, + )!; +@@ -67,7 +67,7 @@ use net::ip; + uri { + scheme = "mailto", + host = "", +- path = "~sircmpwn/hare-dev@lists.sr.ht", ++ raw_path = "~sircmpwn/hare-dev@lists.sr.ht", + ... + }, + )!; +@@ -76,7 +76,7 @@ use net::ip; + uri { + scheme = "http", + host = "", +- path = "/foo/bar", ++ raw_path = "/foo/bar", + ... + }, + )!; +@@ -85,7 +85,7 @@ use net::ip; + uri { + scheme = "http", + host = "", +- path = "/", ++ raw_path = "/", + ... + }, + )!; +@@ -94,7 +94,7 @@ use net::ip; + uri { + scheme = "https", + host = "sr.ht", +- path = "/projects", ++ raw_path = "/projects", + query = "search=%23risc-v&sort=longest-active", + fragment = "foo", + ... +@@ -105,7 +105,7 @@ use net::ip; + uri { + scheme = "https", + host = "en.wiktionary.org", +- path = "/wiki/おはよう", ++ raw_path = "/wiki/%E3%81%8A%E3%81%AF%E3%82%88%E3%81%86", + fragment = "Japanese", + ... + } +@@ -135,11 +135,11 @@ use net::ip; + + @test fn percent_encoding() void = { + test_uri( +- "https://git%2esr.ht/~sircmpw%6e/hare#Build%20status", ++ "https://git.sr.ht/~sircmpwn/hare#Build%20status", + uri { + scheme = "https", + host = "git.sr.ht", +- path = "/~sircmpwn/hare", ++ raw_path = "/~sircmpwn/hare", + fragment = "Build status", + ... + }, +@@ -152,7 +152,7 @@ use net::ip; + uri { + scheme = "ldap", + host = ip::parse("2001:db8::7")!, +- path = "/c=GB", ++ raw_path = "/c=GB", + query = "objectClass?one", + ... + }, +@@ -161,11 +161,11 @@ use net::ip; + + // https://bugs.chromium.org/p/chromium/issues/detail?id=841105 + test_uri( +- "https://web-safety.net/..;@www.google.com:%3443", ++ "https://web-safety.net/..;@www.google.com:443", + uri { + scheme = "https", + host = "web-safety.net", +- path = "/..;@www.google.com:443", ++ raw_path = "/..;@www.google.com:443", + ... + }, + "https://web-safety.net/..;@www.google.com:443", +@@ -180,6 +180,7 @@ fn test_uri(in: str, expected_uri: uri, expected_str: str) (void | invalid) = { + const u = parse(in)?; + defer finish(&u); + ++ + assert_str(u.scheme, expected_uri.scheme); + match (u.host) { + case let s: str => +@@ -189,7 +190,7 @@ fn test_uri(in: str, expected_uri: uri, expected_str: str) (void | invalid) = { + }; + assert(u.port == expected_uri.port); + assert_str(u.userinfo, expected_uri.userinfo); +- assert_str(u.path, expected_uri.path); ++ assert_str(u.raw_path, expected_uri.raw_path); + assert_str(u.query, expected_uri.query); + assert_str(u.fragment, expected_uri.fragment); + +diff --git a/net/uri/fmt.ha b/net/uri/fmt.ha +index 48a43f24..07cb3f7b 100644 +--- a/net/uri/fmt.ha ++++ b/net/uri/fmt.ha +@@ -20,9 +20,9 @@ use strings; + // query = *( pchar / "/" / "?" ) + // fragment = *( pchar / "/" / "?" ) + +-def unres_host: str = "-._~!$&'()*+,;="; +-def unres_query_frag: str = "-._~!$&'()*+,;=:@/?"; +-def unres_path: str = "-._~!$&'()*+,;=:@/"; ++export def unres_host: str = "-._~!$&'()*+,;="; ++export def unres_query_frag: str = "-._~!$&'()*+,;=:@/?"; ++export def unres_path: str = "-._~!$&'()*+,;=:@/"; + + // Writes a formatted [[uri]] to an [[io::handle]]. Returns the number of bytes + // written. +@@ -63,10 +63,10 @@ export fn fmt(out: io::handle, u: *const uri) (size | io::error) = { + if (u.port != 0) { + n += fmt::fprintf(out, ":{}", u.port)?; + }; +- if (has_host && len(u.path) > 0 && !strings::hasprefix(u.path, '/')) { ++ if (has_host && len(u.raw_path) > 0 && !strings::hasprefix(u.raw_path, '/')) { + n += fmt::fprint(out, "/")?; + }; +- n += percent_encode(out, u.path, unres_path)?; ++ n += memio::concat(out, u.raw_path)?; + if (len(u.query) > 0) { + // Always percent-encoded, see parse and encodequery/decodequery + n += fmt::fprintf(out, "?{}", u.query)?; +@@ -92,7 +92,7 @@ fn fmtaddr(out: io::handle, addr: ip::addr) (size | io::error) = { + return n; + }; + +-fn percent_encode(out: io::handle, src: str, allowed: str) (size | io::error) = { ++export fn percent_encode(out: io::handle, src: str, allowed: str) (size | io::error) = { + let iter = strings::iter(src); + let n = 0z; + for (let r => strings::next(&iter)) { +diff --git a/net/uri/parse.ha b/net/uri/parse.ha +index f2522c01..e108bd75 100644 +--- a/net/uri/parse.ha ++++ b/net/uri/parse.ha +@@ -22,10 +22,10 @@ export fn parse(in: str) (uri | invalid) = { + defer if (!success) free(scheme); + + // Determine hier-part variant +- let path = ""; ++ let raw_path = ""; + let authority: ((str | ip::addr6), u16, str) = ("", 0u16, ""); + defer if (!success) { +- free(path); ++ free(raw_path); + free_host(authority.0); + free(authority.2); + }; +@@ -50,7 +50,7 @@ export fn parse(in: str) (uri | invalid) = { + case '/' => + // path-absolute + strings::prev(&in); +- path = parse_path(&in, ++ raw_path = parse_path(&in, + path_mode::ABSOLUTE)?; + case => + return invalid; +@@ -61,17 +61,17 @@ export fn parse(in: str) (uri | invalid) = { + // path-absolute + strings::prev(&in); // return current token + strings::prev(&in); // return leading slash +- path = parse_path(&in, path_mode::ABSOLUTE)?; ++ raw_path = parse_path(&in, path_mode::ABSOLUTE)?; + }; + case => + // path-absolute (just '/') + strings::prev(&in); // return leading slash +- path = parse_path(&in, path_mode::ABSOLUTE)?; ++ raw_path = parse_path(&in, path_mode::ABSOLUTE)?; + }; + case => + // path-rootless + strings::prev(&in); +- path = parse_path(&in, path_mode::ROOTLESS)?; ++ raw_path = parse_path(&in, path_mode::ROOTLESS)?; + }; + case => void; // path-empty + }; +@@ -118,7 +118,7 @@ export fn parse(in: str) (uri | invalid) = { + port = authority.1, + userinfo = authority.2, + +- path = path, ++ raw_path = raw_path, + query = query, + fragment = fragment, + }; +@@ -274,7 +274,7 @@ fn parse_path(in: *strings::iterator, mode: path_mode) (str | invalid) = { + }; + }; + +- return percent_decode(strings::slice(©, in)); ++ return strings::dup(strings::slice(©, in))!; + }; + + fn parse_query(in: *strings::iterator) (str | invalid) = { +@@ -323,13 +323,14 @@ fn parse_port(in: *strings::iterator) (u16 | invalid) = { + }; + }; + +-fn percent_decode(s: str) (str | invalid) = { ++// must be freed by caller ++export fn percent_decode(s: str) (str | invalid) = { + let buf = memio::dynamic(); + percent_decode_static(&buf, s)?; + return memio::string(&buf)!; + }; + +-fn percent_decode_static(out: io::handle, s: str) (void | invalid) = { ++export fn percent_decode_static(out: io::handle, s: str) (void | invalid) = { + let iter = strings::iter(s); + let tmp = memio::dynamic(); + defer io::close(&tmp)!; +diff --git a/net/uri/uri.ha b/net/uri/uri.ha +index 623ffafb..3b7b7c4c 100644 +--- a/net/uri/uri.ha ++++ b/net/uri/uri.ha +@@ -12,7 +12,7 @@ export type uri = struct { + port: u16, + userinfo: str, + +- path: str, ++ raw_path: str, + query: str, + fragment: str, + }; +@@ -31,7 +31,7 @@ export fn dup(u: *uri) uri = { + port = u.port, + userinfo = strings::dup(u.userinfo)!, + +- path = strings::dup(u.path)!, ++ raw_path = strings::dup(u.raw_path)!, + query = strings::dup(u.query)!, + fragment = strings::dup(u.fragment)!, + }; +@@ -46,7 +46,7 @@ export fn finish(u: *uri) void = { + case => void; + }; + free(u.userinfo); +- free(u.path); ++ free(u.raw_path); + free(u.query); + free(u.fragment); + }; +``` |