[prev in list] [next in list] [prev in thread] [next in thread] 

List:       httpcomponents-commits
Subject:    [httpcomponents-core] branch master updated: HTTPCORE-616: Make parsing IPv6 ready
From:       ckozak () apache ! org
Date:       2021-04-20 12:35:32
Message-ID: 161892213249.10249.13800300441895026398 () gitbox ! apache ! org
[Download RAW message or body]

This is an automated email from the ASF dual-hosted git repository.

ckozak pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git


The following commit(s) were added to refs/heads/master by this push:
     new 041b4a7  HTTPCORE-616: Make parsing IPv6 ready
041b4a7 is described below

commit 041b4a7f2b6d7beecdce7ac7b1b304d017a3f8d1
Author: Carter Kozak <ckozak@apache.org>
AuthorDate: Mon Apr 5 15:25:23 2021 -0400

    HTTPCORE-616: Make parsing IPv6 ready
    
    This adds support for bracketed IPv6 host parsing to the following:
    * `org.apache.hc.core5.net.Host.create(String)`
    * `org.apache.hc.core5.net.URIAuthority.create(String)`
    * `org.apache.hc.core5.http.HttpHost.create(String)`
    
    This commit does not address `InetAddressUtils: Parsing may fail when an
    IPv6 scope id might be provided.`
---
 .../main/java/org/apache/hc/core5/net/Host.java    | 26 ++++++++++++--
 .../java/org/apache/hc/core5/net/URISupport.java   |  2 ++
 .../org/apache/hc/core5/http/TestHttpHost.java     | 40 ++++++++++++++++++++++
 .../java/org/apache/hc/core5/net/TestHost.java     | 33 ++++++++++++++++++
 .../org/apache/hc/core5/net/TestURIAuthority.java  | 31 +++++++++++++++++
 5 files changed, 130 insertions(+), 2 deletions(-)

diff --git a/httpcore5/src/main/java/org/apache/hc/core5/net/Host.java \
b/httpcore5/src/main/java/org/apache/hc/core5/net/Host.java index d915b0e..2feda01 \
                100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/net/Host.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/net/Host.java
@@ -60,7 +60,21 @@ public final class Host implements NamedEndpoint, Serializable {
 
     static Host parse(final CharSequence s, final Tokenizer.Cursor cursor) throws \
URISyntaxException {  final Tokenizer tokenizer = Tokenizer.INSTANCE;
-        final String hostName = tokenizer.parseContent(s, cursor, \
URISupport.PORT_SEPARATORS); +        final String hostName;
+        final boolean ipv6Brackets = !cursor.atEnd() && s.charAt(cursor.getPos()) == \
'['; +        if (ipv6Brackets) {
+            cursor.updatePos(cursor.getPos() + 1);
+            hostName = tokenizer.parseContent(s, cursor, \
URISupport.IPV6_HOST_TERMINATORS); +            if (cursor.atEnd() || \
!(s.charAt(cursor.getPos()) == ']')) { +                throw \
URISupport.createException(s, cursor, "Expected an IPv6 closing bracket ']'"); +      \
} +            cursor.updatePos(cursor.getPos() + 1);
+            if (!InetAddressUtils.isIPv6Address(hostName)) {
+                throw URISupport.createException(s, cursor, "Expected an IPv6 \
address"); +            }
+        } else {
+            hostName = tokenizer.parseContent(s, cursor, \
URISupport.PORT_SEPARATORS); +        }
         String portText = null;
         if (!cursor.atEnd() && s.charAt(cursor.getPos()) == ':') {
             cursor.updatePos(cursor.getPos() + 1);
@@ -68,6 +82,9 @@ public final class Host implements NamedEndpoint, Serializable {
         }
         final int port;
         if (!TextUtils.isBlank(portText)) {
+            if (!ipv6Brackets && portText.contains(":")) {
+                throw URISupport.createException(s, cursor, "Expected IPv6 address \
to be enclosed in brackets"); +            }
             try {
                 port = Integer.parseInt(portText);
             } catch (final NumberFormatException ex) {
@@ -85,7 +102,12 @@ public final class Host implements NamedEndpoint, Serializable {
     }
 
     static void format(final StringBuilder buf, final NamedEndpoint endpoint) {
-        buf.append(endpoint.getHostName());
+        final String hostName = endpoint.getHostName();
+        if (InetAddressUtils.isIPv6Address(hostName)) {
+            buf.append('[').append(hostName).append(']');
+        } else {
+            buf.append(hostName);
+        }
         if (endpoint.getPort() != -1) {
             buf.append(":");
             buf.append(endpoint.getPort());
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/net/URISupport.java \
b/httpcore5/src/main/java/org/apache/hc/core5/net/URISupport.java index \
                6948dc8..e884794 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/net/URISupport.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/net/URISupport.java
@@ -34,6 +34,7 @@ import org.apache.hc.core5.util.Tokenizer;
 final class URISupport {
 
     static final BitSet HOST_SEPARATORS = new BitSet(256);
+    static final BitSet IPV6_HOST_TERMINATORS = new BitSet(256);
     static final BitSet PORT_SEPARATORS = new BitSet(256);
     static final BitSet TERMINATORS = new BitSet(256);
 
@@ -43,6 +44,7 @@ final class URISupport {
         TERMINATORS.set('?');
         HOST_SEPARATORS.or(TERMINATORS);
         HOST_SEPARATORS.set('@');
+        IPV6_HOST_TERMINATORS.set(']');
         PORT_SEPARATORS.or(TERMINATORS);
         PORT_SEPARATORS.set(':');
     }
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/TestHttpHost.java \
b/httpcore5/src/test/java/org/apache/hc/core5/http/TestHttpHost.java index \
                54019d1..f944f2f 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/TestHttpHost.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/TestHttpHost.java
@@ -230,4 +230,44 @@ public class TestHttpHost {
         }
     }
 
+    @Test
+    public void testIpv6HostAndPort() throws Exception {
+        final HttpHost host = HttpHost.create("[::1]:80");
+        Assert.assertEquals("http", host.getSchemeName());
+        Assert.assertEquals("::1", host.getHostName());
+        Assert.assertEquals(80, host.getPort());
+    }
+
+    @Test
+    public void testIpv6HostAndPortWithScheme() throws Exception {
+        final HttpHost host = HttpHost.create("https://[::1]:80");
+        Assert.assertEquals("https", host.getSchemeName());
+        Assert.assertEquals("::1", host.getHostName());
+        Assert.assertEquals(80, host.getPort());
+    }
+
+    @Test
+    public void testIpv6HostAndPortWithoutBrackets() throws Exception {
+        try {
+            // ambiguous
+            HttpHost.create("::1:80");
+            Assert.fail("URISyntaxException expected");
+        } catch (final URISyntaxException expected) {
+        }
+    }
+
+    @Test
+    public void testIpv6HostWithoutPort() throws Exception {
+        try {
+            HttpHost.create("::1");
+            Assert.fail("URISyntaxException expected");
+        } catch (final URISyntaxException expected) {
+        }
+    }
+
+    @Test
+    public void testIpv6HostToString() {
+        Assert.assertEquals("http://[::1]:80", new HttpHost("::1", 80).toString());
+        Assert.assertEquals("http://[::1]", new HttpHost("::1", -1).toString());
+    }
 }
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/net/TestHost.java \
b/httpcore5/src/test/java/org/apache/hc/core5/net/TestHost.java index \
                71f35d5..d03a35a 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/net/TestHost.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/net/TestHost.java
@@ -129,4 +129,37 @@ public class TestHost {
         }
     }
 
+    @Test
+    public void testIpv6HostAndPort() throws Exception {
+        final Host host = Host.create("[::1]:80");
+        Assert.assertEquals("::1", host.getHostName());
+        Assert.assertEquals(80, host.getPort());
+    }
+
+    @Test
+    public void testIpv6HostAndPortWithoutBrackets() {
+        try {
+            // ambiguous
+            Host.create("::1:80");
+            Assert.fail("URISyntaxException expected");
+        } catch (final URISyntaxException expected) {
+            Assert.assertTrue(expected.getMessage().contains("Expected IPv6 address \
to be enclosed in brackets")); +        }
+    }
+
+    @Test
+    public void testIpv6HostWithoutPort() {
+        try {
+            Host.create("::1");
+            Assert.fail("URISyntaxException expected");
+        } catch (final URISyntaxException expected) {
+            Assert.assertTrue(expected.getMessage().contains("Expected IPv6 address \
to be enclosed in brackets")); +        }
+    }
+
+    @Test
+    public void testIpv6HostToString() {
+        Assert.assertEquals("[::1]:80", new Host("::1", 80).toString());
+        Assert.assertEquals("[::1]", new Host("::1", -1).toString());
+    }
 }
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/net/TestURIAuthority.java \
b/httpcore5/src/test/java/org/apache/hc/core5/net/TestURIAuthority.java index \
                8aa4a22..3fd972c 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/net/TestURIAuthority.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/net/TestURIAuthority.java
@@ -220,4 +220,35 @@ public class TestURIAuthority {
         }
     }
 
+    @Test
+    public void testCreateFromIPv6String() throws Exception {
+        Assert.assertEquals(new URIAuthority("::1", 8080), \
URIAuthority.create("[::1]:8080")); +        Assert.assertEquals(new \
URIAuthority("::1", -1), URIAuthority.create("[::1]")); +        try {
+            URIAuthority.create("::1");
+            Assert.fail("URISyntaxException expected");
+        } catch (final URISyntaxException expected) {
+        }
+        try {
+            URIAuthority.create("[::1");
+            Assert.fail("URISyntaxException expected");
+        } catch (final URISyntaxException expected) {
+            Assert.assertTrue(expected.getMessage().contains("Expected an IPv6 \
closing bracket")); +        }
+
+        try {
+            URIAuthority.create("[a]:8080");
+            Assert.fail("URISyntaxException expected");
+        } catch (final URISyntaxException expected) {
+            Assert.assertTrue(expected.getMessage().contains("Expected an IPv6 \
address")); +        }
+    }
+
+    @Test
+    public void testIpv6HostToString() {
+        Assert.assertEquals("[::1]:80", new URIAuthority("::1", 80).toString());
+        Assert.assertEquals("user@[::1]:80", new URIAuthority("user", "::1", \
80).toString()); +        Assert.assertEquals("[::1]", new URIAuthority("::1", \
-1).toString()); +        Assert.assertEquals("user@[::1]", new URIAuthority("user", \
"::1", -1).toString()); +    }
 }


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic