| ... | @@ -191,7 +191,11 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri { | ... | @@ -191,7 +191,11 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri { |
| 191 | } | 191 | } |
| 192 | | 192 | |
| 193 | var start_of_host: usize = 0; | 193 | var start_of_host: usize = 0; |
| 194 | if (std.mem.find(u8, authority, "@")) |index| { | 194 | // Use findLast to handle unencoded @ in userinfo gracefully, |
| | 195 | // e.g. scheme://user:p@ssword@hostname. This deviates from RFC3986 |
| | 196 | // (which requires @ to be percent-encoded as %40 in userinfo) but |
| | 197 | // is more robust against URIs in the wild. |
| | 198 | if (std.mem.findLast(u8, authority, "@")) |index| { |
| 195 | start_of_host = index + 1; | 199 | start_of_host = index + 1; |
| 196 | const user_info = authority[0..index]; | 200 | const user_info = authority[0..index]; |
| 197 | | 201 | |
| ... | @@ -621,6 +625,23 @@ test "authority" { | ... | @@ -621,6 +625,23 @@ test "authority" { |
| 621 | try std.testing.expectEqual(@as(u16, 1234), (try parse("scheme://user:password@hostname:1234")).port.?); | 625 | try std.testing.expectEqual(@as(u16, 1234), (try parse("scheme://user:password@hostname:1234")).port.?); |
| 622 | try std.testing.expectEqualStrings("user", (try parse("scheme://user:password@hostname:1234")).user.?.percent_encoded); | 626 | try std.testing.expectEqualStrings("user", (try parse("scheme://user:password@hostname:1234")).user.?.percent_encoded); |
| 623 | try std.testing.expectEqualStrings("password", (try parse("scheme://user:password@hostname:1234")).password.?.percent_encoded); | 627 | try std.testing.expectEqualStrings("password", (try parse("scheme://user:password@hostname:1234")).password.?.percent_encoded); |
| | 628 | |
| | 629 | try std.testing.expectEqualStrings("user", (try parse("scheme://user:p@ssword@hostname:1234")).user.?.percent_encoded); |
| | 630 | try std.testing.expectEqualStrings("p@ssword", (try parse("scheme://user:p@ssword@hostname:1234")).password.?.percent_encoded); |
| | 631 | try std.testing.expectEqualStrings("hostname", (try parse("scheme://user:p@ssword@hostname:1234")).host.?.percent_encoded); |
| | 632 | |
| | 633 | try std.testing.expectEqualStrings("user", (try parse("scheme://user:p@@@word@hostname:1234")).user.?.percent_encoded); |
| | 634 | try std.testing.expectEqualStrings("p@@@word", (try parse("scheme://user:p@@@word@hostname:1234")).password.?.percent_encoded); |
| | 635 | try std.testing.expectEqualStrings("hostname", (try parse("scheme://user:p@@@word@hostname:1234")).host.?.percent_encoded); |
| | 636 | |
| | 637 | try std.testing.expectEqualStrings("user@name", (try parse("scheme://user@name@hostname")).user.?.percent_encoded); |
| | 638 | try std.testing.expectEqual(@as(?Component, null), (try parse("scheme://user@name@hostname")).password); |
| | 639 | try std.testing.expectEqualStrings("hostname", (try parse("scheme://user@name@hostname")).host.?.percent_encoded); |
| | 640 | |
| | 641 | try std.testing.expectEqualStrings("user@name", (try parse("scheme://user@name@hostname:1234")).user.?.percent_encoded); |
| | 642 | try std.testing.expectEqual(@as(?Component, null), (try parse("scheme://user@name@hostname:1234")).password); |
| | 643 | try std.testing.expectEqualStrings("hostname", (try parse("scheme://user@name@hostname:1234")).host.?.percent_encoded); |
| | 644 | try std.testing.expectEqual(@as(u16, 1234), (try parse("scheme://user@name@hostname:1234")).port.?); |
| 624 | } | 645 | } |
| 625 | | 646 | |
| 626 | test "authority.password" { | 647 | test "authority.password" { |