You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2020/07/25 10:04:54 UTC
[httpcomponents-core] 02/02: Better parse and format methods for
URIAuthority
This is an automated email from the ASF dual-hosted git repository.
olegk pushed a commit to branch 5.1.x
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git
commit 48172924c1bd46ce5bca33737e349b4420184c7f
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Sat Jul 25 12:00:15 2020 +0200
Better parse and format methods for URIAuthority
---
.../java/org/apache/hc/core5/net/URIAuthority.java | 135 +++++++++++++++------
.../org/apache/hc/core5/net/TestURIAuthority.java | 88 ++++++++++++--
2 files changed, 181 insertions(+), 42 deletions(-)
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/net/URIAuthority.java b/httpcore5/src/main/java/org/apache/hc/core5/net/URIAuthority.java
index 01feb0f..1cae817 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/net/URIAuthority.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/net/URIAuthority.java
@@ -29,6 +29,7 @@ package org.apache.hc.core5.net;
import java.io.Serializable;
import java.net.URISyntaxException;
+import java.util.BitSet;
import java.util.Locale;
import org.apache.hc.core5.annotation.Contract;
@@ -36,6 +37,7 @@ import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.util.Args;
import org.apache.hc.core5.util.LangUtils;
import org.apache.hc.core5.util.TextUtils;
+import org.apache.hc.core5.util.Tokenizer;
/**
* Represents authority component of request {@link java.net.URI}.
@@ -50,6 +52,97 @@ public final class URIAuthority implements NamedEndpoint, Serializable {
private final String hostname;
private final int port;
+ private static final BitSet HOST_SEPARATORS = new BitSet(256);
+ private static final BitSet PORT_SEPARATORS = new BitSet(256);
+ private static final BitSet TERMINATORS = new BitSet(256);
+
+ static {
+ TERMINATORS.set('/');
+ TERMINATORS.set('#');
+ TERMINATORS.set('?');
+ HOST_SEPARATORS.or(TERMINATORS);
+ HOST_SEPARATORS.set('@');
+ HOST_SEPARATORS.set(':');
+ PORT_SEPARATORS.or(TERMINATORS);
+ PORT_SEPARATORS.set(':');
+ }
+
+ static URISyntaxException createException(
+ final CharSequence input, final Tokenizer.Cursor cursor, final String reason) {
+ return new URISyntaxException(
+ input.subSequence(cursor.getLowerBound(), cursor.getUpperBound()).toString(),
+ reason,
+ cursor.getPos());
+ }
+
+ static URIAuthority parse(final CharSequence s, final Tokenizer.Cursor cursor) throws URISyntaxException {
+ final Tokenizer tokenizer = Tokenizer.INSTANCE;
+ String userInfo = null;
+ String hostName = null;
+ String portText = null;
+ final String token = tokenizer.parseContent(s, cursor, HOST_SEPARATORS);
+ if (!cursor.atEnd()) {
+ final char separator1 = s.charAt(cursor.getPos());
+ if (separator1 == '@') {
+ userInfo = !TextUtils.isEmpty(token) ? token : null;
+ cursor.updatePos(cursor.getPos() + 1);
+ hostName = tokenizer.parseContent(s, cursor, PORT_SEPARATORS);
+ if (!cursor.atEnd()) {
+ final char separator2 = s.charAt(cursor.getPos());
+ if (separator2 == ':') {
+ cursor.updatePos(cursor.getPos() + 1);
+ portText = tokenizer.parseContent(s, cursor, TERMINATORS);
+ }
+ }
+ } else {
+ hostName = token;
+ if (separator1 == ':') {
+ cursor.updatePos(cursor.getPos() + 1);
+ portText = tokenizer.parseContent(s, cursor, TERMINATORS);
+ }
+ }
+ } else {
+ hostName = token;
+ }
+ if (TextUtils.isBlank(hostName)) {
+ throw createException(s, cursor, "Authority host is empty");
+ }
+ final int port;
+ if (!TextUtils.isBlank(portText)) {
+ try {
+ port = Integer.parseInt(portText);
+ } catch (final NumberFormatException ex) {
+ throw createException(s, cursor, "Authority port is invalid");
+ }
+ } else {
+ port = -1;
+ }
+ return new URIAuthority(userInfo, hostName.toLowerCase(Locale.ROOT), port, true);
+ }
+
+ static URIAuthority parse(final CharSequence s) throws URISyntaxException {
+ final Tokenizer.Cursor cursor = new Tokenizer.Cursor(0, s.length());
+ return parse(s, cursor);
+ }
+
+ static void format(final StringBuilder buf, final URIAuthority uriAuthority) {
+ if (uriAuthority.userInfo != null) {
+ buf.append(uriAuthority.userInfo);
+ buf.append("@");
+ }
+ buf.append(uriAuthority.hostname);
+ if (uriAuthority.port != -1) {
+ buf.append(":");
+ buf.append(uriAuthority.port);
+ }
+ }
+
+ static String format(final URIAuthority uriAuthority) {
+ final StringBuilder buf = new StringBuilder();
+ format(buf, uriAuthority);
+ return buf.toString();
+ }
+
/**
* @throws IllegalArgumentException
* If the port parameter is outside the specified range of valid port values, which is between 0 and
@@ -90,33 +183,15 @@ public final class URIAuthority implements NamedEndpoint, Serializable {
* Creates {@code URIHost} instance from string. Text may not contain any blanks.
*/
public static URIAuthority create(final String s) throws URISyntaxException {
- if (s == null) {
+ if (TextUtils.isBlank(s)) {
return null;
}
- String userInfo = null;
- String hostname = s;
- int port = -1;
- final int portIdx = hostname.lastIndexOf(":");
- if (portIdx > 0) {
- try {
- port = Integer.parseInt(hostname.substring(portIdx + 1));
- } catch (final NumberFormatException ex) {
- throw new URISyntaxException(s, "invalid port");
- }
- hostname = hostname.substring(0, portIdx);
- }
- final int atIdx = hostname.lastIndexOf("@");
- if (atIdx > 0) {
- userInfo = hostname.substring(0, atIdx);
- if (TextUtils.containsBlanks(userInfo)) {
- throw new URISyntaxException(s, "user info contains blanks");
- }
- hostname = hostname.substring(atIdx + 1);
- }
- if (TextUtils.containsBlanks(hostname)) {
- throw new URISyntaxException(s, "hostname contains blanks");
+ final Tokenizer.Cursor cursor = new Tokenizer.Cursor(0, s.length());
+ final URIAuthority uriAuthority = parse(s, cursor);
+ if (!cursor.atEnd()) {
+ throw createException(s, cursor, "Unexpected content");
}
- return new URIAuthority(userInfo, hostname.toLowerCase(Locale.ROOT), port, true);
+ return uriAuthority;
}
public URIAuthority(final String hostname) {
@@ -139,17 +214,7 @@ public final class URIAuthority implements NamedEndpoint, Serializable {
@Override
public String toString() {
- final StringBuilder buffer = new StringBuilder();
- if (userInfo != null) {
- buffer.append(userInfo);
- buffer.append("@");
- }
- buffer.append(hostname);
- if (port != -1) {
- buffer.append(":");
- buffer.append(Integer.toString(port));
- }
- return buffer.toString();
+ return format(this);
}
@Override
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 570e1d6..76c3b41 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
@@ -33,6 +33,8 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.URISyntaxException;
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.MatcherAssert;
import org.junit.Assert;
import org.junit.Test;
@@ -118,19 +120,91 @@ public class TestURIAuthority {
}
@Test
+ public void testParse() throws Exception {
+ MatcherAssert.assertThat(URIAuthority.parse("somehost"),
+ CoreMatchers.equalTo(new URIAuthority("somehost", -1)));
+ MatcherAssert.assertThat(URIAuthority.parse("somehost/blah"),
+ CoreMatchers.equalTo(new URIAuthority("somehost", -1)));
+ MatcherAssert.assertThat(URIAuthority.parse("somehost?blah"),
+ CoreMatchers.equalTo(new URIAuthority("somehost", -1)));
+ MatcherAssert.assertThat(URIAuthority.parse("somehost#blah"),
+ CoreMatchers.equalTo(new URIAuthority("somehost", -1)));
+ try {
+ URIAuthority.create("aaaa@:8080");
+ Assert.fail("URISyntaxException expected");
+ } catch (final URISyntaxException expected) {
+ }
+ try {
+ URIAuthority.create("@:");
+ Assert.fail("URISyntaxException expected");
+ } catch (final URISyntaxException expected) {
+ }
+ MatcherAssert.assertThat(URIAuthority.parse("somehost:8080"),
+ CoreMatchers.equalTo(new URIAuthority("somehost", 8080)));
+ MatcherAssert.assertThat(URIAuthority.parse("somehost:8080/blah"),
+ CoreMatchers.equalTo(new URIAuthority("somehost", 8080)));
+ MatcherAssert.assertThat(URIAuthority.parse("somehost:8080?blah"),
+ CoreMatchers.equalTo(new URIAuthority("somehost", 8080)));
+ MatcherAssert.assertThat(URIAuthority.parse("somehost:8080#blah"),
+ CoreMatchers.equalTo(new URIAuthority("somehost", 8080)));
+ MatcherAssert.assertThat(URIAuthority.parse("somehost:008080"),
+ CoreMatchers.equalTo(new URIAuthority("somehost", 8080)));
+ try {
+ URIAuthority.create("somehost:aaaaa");
+ Assert.fail("URISyntaxException expected");
+ } catch (final URISyntaxException expected) {
+ }
+ try {
+ URIAuthority.create("somehost:90ab");
+ Assert.fail("URISyntaxException expected");
+ } catch (final URISyntaxException expected) {
+ }
+
+ MatcherAssert.assertThat(URIAuthority.parse("someuser@somehost"),
+ CoreMatchers.equalTo(new URIAuthority("someuser", "somehost", -1)));
+ MatcherAssert.assertThat(URIAuthority.parse("someuser@somehost/blah"),
+ CoreMatchers.equalTo(new URIAuthority("someuser", "somehost", -1)));
+ MatcherAssert.assertThat(URIAuthority.parse("someuser@somehost?blah"),
+ CoreMatchers.equalTo(new URIAuthority("someuser", "somehost", -1)));
+ MatcherAssert.assertThat(URIAuthority.parse("someuser@somehost#blah"),
+ CoreMatchers.equalTo(new URIAuthority("someuser", "somehost", -1)));
+
+ MatcherAssert.assertThat(URIAuthority.parse("someuser@somehost:"),
+ CoreMatchers.equalTo(new URIAuthority("someuser", "somehost", -1)));
+ MatcherAssert.assertThat(URIAuthority.parse("someuser@somehost:/blah"),
+ CoreMatchers.equalTo(new URIAuthority("someuser", "somehost", -1)));
+ MatcherAssert.assertThat(URIAuthority.parse("someuser@somehost:?blah"),
+ CoreMatchers.equalTo(new URIAuthority("someuser", "somehost", -1)));
+ MatcherAssert.assertThat(URIAuthority.parse("someuser@somehost:#blah"),
+ CoreMatchers.equalTo(new URIAuthority("someuser", "somehost", -1)));
+
+ MatcherAssert.assertThat(URIAuthority.parse("someuser@somehost:8080"),
+ CoreMatchers.equalTo(new URIAuthority("someuser", "somehost", 8080)));
+ MatcherAssert.assertThat(URIAuthority.parse("someuser@somehost:8080/blah"),
+ CoreMatchers.equalTo(new URIAuthority("someuser", "somehost", 8080)));
+ MatcherAssert.assertThat(URIAuthority.parse("someuser@somehost:8080?blah"),
+ CoreMatchers.equalTo(new URIAuthority("someuser", "somehost", 8080)));
+ MatcherAssert.assertThat(URIAuthority.parse("someuser@somehost:8080#blah"),
+ CoreMatchers.equalTo(new URIAuthority("someuser", "somehost", 8080)));
+ MatcherAssert.assertThat(URIAuthority.parse("@somehost:8080"),
+ CoreMatchers.equalTo(new URIAuthority("somehost", 8080)));
+ }
+
+ @Test
public void testCreateFromString() throws Exception {
Assert.assertEquals(new URIAuthority("somehost", 8080), URIAuthority.create("somehost:8080"));
- Assert.assertEquals(new URIAuthority("somehost", 8080), URIAuthority.create("SomeHost:8080"));
+ Assert.assertEquals(new URIAuthority("SomeHost", 8080), URIAuthority.create("SomeHost:8080"));
Assert.assertEquals(new URIAuthority("somehost", 1234), URIAuthority.create("somehost:1234"));
Assert.assertEquals(new URIAuthority("somehost", -1), URIAuthority.create("somehost"));
Assert.assertEquals(new URIAuthority("user", "somehost", -1), URIAuthority.create("user@somehost"));
- }
-
- @Test
- public void testCreateFromStringInvalid() throws Exception {
try {
- URIAuthority.create(" host ");
- Assert.fail("IllegalArgumentException expected");
+ URIAuthority.create(" host");
+ Assert.fail("URISyntaxException expected");
+ } catch (final URISyntaxException expected) {
+ }
+ try {
+ URIAuthority.create("host ");
+ Assert.fail("URISyntaxException expected");
} catch (final URISyntaxException expected) {
}
try {