diff --git a/lib/network/http/h2/h2_codec.dart b/lib/network/http/h2/h2_codec.dart index e9fe5c2..0c0c30a 100644 --- a/lib/network/http/h2/h2_codec.dart +++ b/lib/network/http/h2/h2_codec.dart @@ -451,10 +451,24 @@ class Http2RequestDecoder extends Http2Codec { // 解析 authority,提取主机和端口 String host = authority; int port = (scheme == 'https' ? 443 : 80); - if (authority.contains(':')) { - var parts = authority.split(':'); - host = parts[0]; - port = int.tryParse(parts[1]) ?? (scheme == 'https' ? 443 : 80); + + if (authority.startsWith("[")) { + int closeBracketIndex = authority.indexOf(']'); + if (closeBracketIndex != -1) { + host = authority.substring(0, closeBracketIndex + 1); + if (authority.length > closeBracketIndex + 1 && authority[closeBracketIndex + 1] == ':') { + port = int.tryParse(authority.substring(closeBracketIndex + 2)) ?? port; + } + } + } else { + int lastColonIndex = authority.lastIndexOf(':'); + if (lastColonIndex != -1) { + var p = int.tryParse(authority.substring(lastColonIndex + 1)); + if (p != null) { + host = authority.substring(0, lastColonIndex); + port = p; + } + } } httpRequest.hostAndPort = HostAndPort("$scheme://", host, port); } diff --git a/lib/network/http/http.dart b/lib/network/http/http.dart index 006a538..ebd0084 100644 --- a/lib/network/http/http.dart +++ b/lib/network/http/http.dart @@ -228,6 +228,7 @@ class HttpRequest extends HttpMessage { _requestUri ??= Uri.parse(requestUrl); return _requestUri; } catch (e) { + logger.w('parse uri error $requestUrl ${hostAndPort?.scheme} ${hostAndPort?.host}: $e'); return null; } } diff --git a/test/temp_ipv6_test.dart b/test/temp_ipv6_test.dart new file mode 100644 index 0000000..3471aad --- /dev/null +++ b/test/temp_ipv6_test.dart @@ -0,0 +1,137 @@ + +import 'package:test/test.dart'; + +void main() { + test('Parsed IPv6 authority correctly', () { + var authority = "[240c:409f:1000::4:0:a5]"; + var scheme = "https"; + + String host = authority; + int port = (scheme == 'https' ? 443 : 80); + + if (authority.startsWith("[")) { + int closeBracketIndex = authority.indexOf(']'); + if (closeBracketIndex != -1) { + host = authority.substring(0, closeBracketIndex + 1); + if (authority.length > closeBracketIndex + 1 && authority[closeBracketIndex + 1] == ':') { + port = int.tryParse(authority.substring(closeBracketIndex + 2)) ?? port; + } + } + } else { + int lastColonIndex = authority.lastIndexOf(':'); + if (lastColonIndex != -1) { + var p = int.tryParse(authority.substring(lastColonIndex + 1)); + if (p != null) { + host = authority.substring(0, lastColonIndex); + port = p; + } + } + } + + expect(host, "[240c:409f:1000::4:0:a5]"); + expect(port, 443); + }); + + test('Parsed IPv6 authority with port correctly', () { + var authority = "[240c:409f:1000::4:0:a5]:8080"; + var scheme = "https"; + + String host = authority; + int port = (scheme == 'https' ? 443 : 80); + + if (authority.startsWith("[")) { + int closeBracketIndex = authority.indexOf(']'); + if (closeBracketIndex != -1) { + host = authority.substring(0, closeBracketIndex + 1); + if (authority.length > closeBracketIndex + 1 && authority[closeBracketIndex + 1] == ':') { + port = int.tryParse(authority.substring(closeBracketIndex + 2)) ?? port; + } + } + } else { + int lastColonIndex = authority.lastIndexOf(':'); + if (lastColonIndex != -1) { + var p = int.tryParse(authority.substring(lastColonIndex + 1)); + if (p != null) { + host = authority.substring(0, lastColonIndex); + port = p; + } + } + } + + expect(host, "[240c:409f:1000::4:0:a5]"); + expect(port, 8080); + }); + + test('Parsed IPv6 authority broken', () { + // case from log: [240c + // Though log says host=[240c, authority was [240c:409f:1000::4:0:a5] + // This testcase is checking if the logic handles incomplete ipv6 gracefully? + // If authority is literally "[240c", it has start [ but no ]. + var authority = "[240c"; + var scheme = "https"; + + String host = authority; + int port = (scheme == 'https' ? 443 : 80); + + if (authority.startsWith("[")) { + int closeBracketIndex = authority.indexOf(']'); + if (closeBracketIndex != -1) { + host = authority.substring(0, closeBracketIndex + 1); + if (authority.length > closeBracketIndex + 1 && authority[closeBracketIndex + 1] == ':') { + port = int.tryParse(authority.substring(closeBracketIndex + 2)) ?? port; + } + } + } else { + // ... + } + // Logic says: if start with [ but no ], host remains authority. + expect(host, "[240c"); + }); + + test('Parsed IPv4 authority correctly', () { + var authority = "192.168.1.1:8080"; + var scheme = "http"; + + String host = authority; + int port = (scheme == 'https' ? 443 : 80); + + if (authority.startsWith("[")) { + // ... + } else { + int lastColonIndex = authority.lastIndexOf(':'); + if (lastColonIndex != -1) { + var p = int.tryParse(authority.substring(lastColonIndex + 1)); + if (p != null) { + host = authority.substring(0, lastColonIndex); + port = p; + } + } + } + expect(host, "192.168.1.1"); + expect(port, 8080); + }); + + test('Parsed simple hostname correctly', () { + var authority = "example.com"; + var scheme = "https"; + + String host = authority; + int port = (scheme == 'https' ? 443 : 80); + + if (authority.startsWith("[")) { + // ... + } else { + int lastColonIndex = authority.lastIndexOf(':'); + if (lastColonIndex != -1) { + var p = int.tryParse(authority.substring(lastColonIndex + 1)); + if (p != null) { + host = authority.substring(0, lastColonIndex); + port = p; + } + } + } + expect(host, "example.com"); + expect(port, 443); + }); +} +