From 4160a6b361884914eb2bf74364b453d3c8be7b59 Mon Sep 17 00:00:00 2001 From: michaellee8 Date: Thu, 1 Jul 2021 01:18:44 +0000 Subject: [PATCH] [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 Commit-Queue: Siva Annamalai --- sdk/lib/_http/http_headers.dart | 9 ++++-- tests/standalone/io/http_headers_test.dart | 34 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/sdk/lib/_http/http_headers.dart b/sdk/lib/_http/http_headers.dart index 77b9c227c44c..09e57487cadb 100644 --- a/sdk/lib/_http/http_headers.dart +++ b/sdk/lib/_http/http_headers.dart @@ -421,8 +421,13 @@ class _HttpHeaders implements HttpHeaders { 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 11e0f899fd35..f2cfb6cd039b 100644 --- a/tests/standalone/io/http_headers_test.dart +++ b/tests/standalone/io/http_headers_test.dart @@ -173,6 +173,40 @@ void testHost() { 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() {