[Http] Fix handling of ipv6 address in host header
The current implementation of _HttpHeaders._addHost does not handle
ipv6 address correctly. This patch fixes the handling and add test
case for that.
References:
- https://github.com/flutter/flutter/issues/83609#issuecomment-870356766
TEST=http_headers_test.dart has been updated with new cases.
Bug: https://github.com/flutter/flutter/issues/83609#issuecomment-870356766
Change-Id: Idc4e9bbe66d66f0d846c7a32a40854201c3b0153
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/205280
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Siva Annamalai <asiva@google.com>
diff --git a/sdk/lib/_http/http_headers.dart b/sdk/lib/_http/http_headers.dart
index 77b9c22..09e5748 100644
--- a/sdk/lib/_http/http_headers.dart
+++ b/sdk/lib/_http/http_headers.dart
@@ -421,8 +421,13 @@
void _addHost(String name, value) {
if (value is String) {
- int pos = value.indexOf(":");
- if (pos == -1) {
+ // value.indexOf will only work for ipv4, ipv6 which has multiple : in its
+ // host part needs lastIndexOf
+ int pos = value.lastIndexOf(":");
+ // According to RFC 3986, section 3.2.2, host part of ipv6 address must be
+ // enclosed by square brackets.
+ // https://serverfault.com/questions/205793/how-can-one-distinguish-the-host-and-the-port-in-an-ipv6-url
+ if (pos == -1 || value.startsWith("[") && value.endsWith("]")) {
_host = value;
_port = HttpClient.defaultHttpPort;
} else {
diff --git a/tests/standalone/io/http_headers_test.dart b/tests/standalone/io/http_headers_test.dart
index 11e0f89..f2cfb6c 100644
--- a/tests/standalone/io/http_headers_test.dart
+++ b/tests/standalone/io/http_headers_test.dart
@@ -173,6 +173,40 @@
Expect.equals(":1234", headers.value(HttpHeaders.hostHeader));
Expect.isNull(headers.host);
Expect.equals(1234, headers.port);
+
+ // ipv4
+ host = "123.45.67.89";
+ int port = 1234;
+ headers = new _HttpHeaders("1.1");
+ headers.add(HttpHeaders.hostHeader, "$host:$port");
+ Expect.equals("$host:$port", headers.value(HttpHeaders.hostHeader));
+ Expect.equals(host, headers.host);
+ Expect.equals(port, headers.port);
+
+ // ipv6: host+port
+ host = "[2001:db8::1]";
+ port = 1234;
+ headers = new _HttpHeaders("1.1");
+ headers.add(HttpHeaders.hostHeader, "$host:$port");
+ Expect.equals("$host:$port", headers.value(HttpHeaders.hostHeader));
+ Expect.equals(host, headers.host);
+ Expect.equals(port, headers.port);
+
+ // ipv6: host only
+ host = "[2001:db8::1]";
+ headers = new _HttpHeaders("1.1");
+ headers.add(HttpHeaders.hostHeader, "$host");
+ Expect.equals("$host", headers.value(HttpHeaders.hostHeader));
+ Expect.equals(host, headers.host);
+ Expect.equals(headers.port, HttpClient.defaultHttpPort);
+
+ // ipv6: host + invalid port
+ host = "[2001:db8::1]";
+ headers = new _HttpHeaders("1.1");
+ headers.add(HttpHeaders.hostHeader, "$host:xxx");
+ Expect.equals("$host:xxx", headers.value(HttpHeaders.hostHeader));
+ Expect.equals(host, headers.host);
+ Expect.isNull(headers.port);
}
void testTransferEncoding() {