diff --git a/vlib/net/urllib/urllib.v b/vlib/net/urllib/urllib.v index 22ec412c8c8137..22114362da63a9 100644 --- a/vlib/net/urllib/urllib.v +++ b/vlib/net/urllib/urllib.v @@ -436,11 +436,15 @@ fn split(s string, sep u8, cutc bool) (string, string) { pub fn parse(rawurl string) !URL { // Cut off #frag u, frag := split(rawurl, `#`, true) - mut url := parse_url(u, false) or { return error(error_msg(err_msg_parse, u)) } + mut url := parse_url(u, false) or { + return error(error_msg(err_msg_parse + '[${err.msg()}]', u)) + } if frag == '' { return url } - f := unescape(frag, .encode_fragment) or { return error(error_msg(err_msg_parse, u)) } + f := unescape(frag, .encode_fragment) or { + return error(error_msg(err_msg_parse + '[${err.msg()}]', u)) + } url.fragment = f return url } @@ -503,12 +507,13 @@ fn parse_url(rawurl string, via_request bool) !URL { // RFC 3986, ยง3.3: // In addition, a URI reference (Section 4.1) may be a relative-path reference, // in which case the first path segment cannot contain a colon (':') character. - colon := rest.index(':') or { return error('there should be a : in the URL') } - slash := rest.index('/') or { return error('there should be a / in the URL') } - if colon >= 0 && (slash < 0 || colon < slash) { - // First path segment has colon. Not allowed in relative URL. - return error(error_msg('parse_url: first path segment in URL cannot contain colon', - '')) + if colon := rest.index(':') { + slash := rest.index('/') or { return error('there should be a / in the URL') } + if colon >= 0 && (slash < 0 || colon < slash) { + // First path segment has colon. Not allowed in relative URL. + return error(error_msg('parse_url: first path segment in URL cannot contain colon', + '')) + } } } if ((url.scheme != '' || !via_request) && !rest.starts_with('///')) && rest.starts_with('//') diff --git a/vlib/net/urllib/urllib_test.v b/vlib/net/urllib/urllib_test.v index 8a3973c3d65bf7..6af3d07654b93d 100644 --- a/vlib/net/urllib/urllib_test.v +++ b/vlib/net/urllib/urllib_test.v @@ -102,6 +102,9 @@ fn test_parse() { 'foo://example.com:8042/over/there?name=ferret#nose', 'ftp://2001:0db8:85a3:0000:0000:8a2e:0370:7334/path/file.txt', 'ws://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:4000', + '/2000k/hls/mixed.m3u8', + '2000k/hls/mixed.m3u8', + './2000k:hls/mixed.m3u8', ] for url in urls { urllib.parse(url)! @@ -112,6 +115,9 @@ fn test_parse() { assert u.scheme == 'https' && u.hostname() == 'www.mydomain.com' && u.port() == '8080' && u.path == '/som/url' && u.fragment == 'testfragment' && u.user.username == 'joe' && u.user.password == 'pass' + + v := urllib.parse('https://vip.ffzy-online4.com/20230205/6094_d2720761/index.m3u8')!.resolve_reference(urllib.parse('2000k/hls/mixed.m3u8')!)! + assert v.str() == 'https://vip.ffzy-online4.com/20230205/6094_d2720761/2000k/hls/mixed.m3u8' } fn test_parse_authority() {