diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/ProtocolVersion.java b/httpcore5/src/main/java/org/apache/hc/core5/http/ProtocolVersion.java
index 572bbc5d9..65f49f3fb 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/ProtocolVersion.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/ProtocolVersion.java
@@ -30,8 +30,10 @@
import java.io.Serializable;
import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.Internal;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.util.Args;
+import org.apache.hc.core5.util.Tokenizer;
/**
* Represents a protocol version. The "major.minor" numbering
@@ -239,6 +241,29 @@ public final boolean lessEquals(final ProtocolVersion version) {
return isComparable(version) && (compareToVersion(version) <= 0);
}
+ @Internal
+ public static ProtocolVersion parse(
+ final CharSequence buffer,
+ final Tokenizer.Cursor cursor,
+ final Tokenizer.Delimiter delimiterPredicate) throws ParseException {
+ return ProtocolVersionParser.INSTANCE.parse(buffer, cursor, delimiterPredicate);
+ }
+
+ /**
+ * @since 5.4
+ */
+ public static ProtocolVersion parse(final String s) throws ParseException {
+ if (s == null) {
+ return null;
+ }
+ final Tokenizer.Cursor cursor = new Tokenizer.Cursor(0, s.length());
+ final ProtocolVersion protocolVersion = ProtocolVersionParser.INSTANCE.parse(s, cursor, null);
+ Tokenizer.INSTANCE.skipWhiteSpace(s, cursor);
+ if (!cursor.atEnd()) {
+ throw new ParseException("Invalid protocol version; trailing content");
+ }
+ return protocolVersion;
+ }
/**
* Converts this protocol version to a string.
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/ProtocolVersionParser.java b/httpcore5/src/main/java/org/apache/hc/core5/http/ProtocolVersionParser.java
new file mode 100644
index 000000000..e574403c8
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/ProtocolVersionParser.java
@@ -0,0 +1,127 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+package org.apache.hc.core5.http;
+
+import org.apache.hc.core5.annotation.Internal;
+import org.apache.hc.core5.util.TextUtils;
+import org.apache.hc.core5.util.Tokenizer;
+
+@Internal
+public class ProtocolVersionParser {
+
+ public final static ProtocolVersionParser INSTANCE = new ProtocolVersionParser();
+
+ private static final char SLASH = '/';
+ private static final char FULL_STOP = '.';
+ private static final Tokenizer.Delimiter PROTO_DELIMITER = Tokenizer.delimiters(SLASH);
+ private static final Tokenizer.Delimiter FULL_STOP_OR_BLANK = Tokenizer.delimiters(FULL_STOP, ' ', '\t');
+ private static final Tokenizer.Delimiter BLANK = Tokenizer.delimiters(' ', '\t');
+ private final Tokenizer tokenizer;
+
+ public ProtocolVersionParser() {
+ this.tokenizer = Tokenizer.INSTANCE;
+ }
+
+ @Internal
+ @FunctionalInterface
+ public interface Factory {
+
+ ProtocolVersion create(int major, int minor);
+
+ }
+
+ public ProtocolVersion parse(
+ final String protocol,
+ final Factory factory,
+ final CharSequence buffer,
+ final Tokenizer.Cursor cursor,
+ final Tokenizer.Delimiter delimiterPredicate) throws ParseException {
+ final int lowerBound = cursor.getLowerBound();
+ final int upperBound = cursor.getUpperBound();
+ final String token1 = tokenizer.parseToken(buffer, cursor,
+ delimiterPredicate != null ? (ch) -> delimiterPredicate.test(ch) || FULL_STOP_OR_BLANK.test(ch) : FULL_STOP_OR_BLANK);
+ final int major;
+ try {
+ major = Integer.parseInt(token1);
+ } catch (final NumberFormatException e) {
+ throw new ParseException("Invalid " + protocol + " major version number",
+ buffer, lowerBound, upperBound, cursor.getPos());
+ }
+ if (cursor.atEnd()) {
+ return factory != null ? factory.create(major, major) : new ProtocolVersion(protocol, major, 0);
+ }
+ if (buffer.charAt(cursor.getPos()) != FULL_STOP) {
+ return factory != null ? factory.create(major, major) : new ProtocolVersion(protocol, major, 0);
+ } else {
+ cursor.updatePos(cursor.getPos() + 1);
+ final String token2 = tokenizer.parseToken(buffer, cursor,
+ delimiterPredicate != null ? (ch) -> delimiterPredicate.test(ch) || BLANK.test(ch) : BLANK);
+ final int minor;
+ try {
+ minor = Integer.parseInt(token2);
+ } catch (final NumberFormatException e) {
+ throw new ParseException("Invalid " + protocol + " minor version number",
+ buffer, lowerBound, upperBound, cursor.getPos());
+ }
+ return factory != null ? factory.create(major, minor) : new ProtocolVersion(protocol, major, minor);
+ }
+ }
+
+ public ProtocolVersion parse(
+ final String protocol,
+ final CharSequence buffer,
+ final Tokenizer.Cursor cursor,
+ final Tokenizer.Delimiter delimiterPredicate) throws ParseException {
+ return parse(protocol, null, buffer, cursor, delimiterPredicate);
+ }
+
+ public ProtocolVersion parse(
+ final String protocol,
+ final CharSequence buffer,
+ final Tokenizer.Cursor cursor) throws ParseException {
+ return parse(protocol, null, buffer, cursor, null);
+ }
+
+ public ProtocolVersion parse(
+ final CharSequence buffer,
+ final Tokenizer.Cursor cursor,
+ final Tokenizer.Delimiter delimiterPredicate) throws ParseException {
+ tokenizer.skipWhiteSpace(buffer, cursor);
+ final String proto = tokenizer.parseToken(buffer, cursor, PROTO_DELIMITER);
+ if (TextUtils.isBlank(proto)) {
+ throw new ParseException("Invalid protocol name");
+ }
+ if (!cursor.atEnd() && buffer.charAt(cursor.getPos()) == SLASH) {
+ cursor.updatePos(cursor.getPos() + 1);
+ return parse(proto, null, buffer, cursor, delimiterPredicate);
+ } else {
+ throw new ParseException("Invalid protocol name");
+ }
+ }
+
+}
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/message/BasicLineParser.java b/httpcore5/src/main/java/org/apache/hc/core5/http/message/BasicLineParser.java
index f73579efc..003fd218c 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/message/BasicLineParser.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/message/BasicLineParser.java
@@ -33,6 +33,7 @@
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.ProtocolVersionParser;
import org.apache.hc.core5.util.Args;
import org.apache.hc.core5.util.CharArrayBuffer;
import org.apache.hc.core5.util.TextUtils;
@@ -48,7 +49,6 @@ public class BasicLineParser implements LineParser {
public final static BasicLineParser INSTANCE = new BasicLineParser();
- private static final Tokenizer.Delimiter FULL_STOP = Tokenizer.delimiters('.');
private static final Tokenizer.Delimiter BLANKS = Tokenizer.delimiters(' ', '\t');
private static final Tokenizer.Delimiter COLON = Tokenizer.delimiters(':');
@@ -108,29 +108,7 @@ ProtocolVersion parseProtocolVersion(
}
cursor.updatePos(pos + protolength + 1);
-
- final String token1 = this.tokenizer.parseToken(buffer, cursor, FULL_STOP);
- final int major;
- try {
- major = Integer.parseInt(token1);
- } catch (final NumberFormatException e) {
- throw new ParseException("Invalid protocol major version number",
- buffer, cursor.getLowerBound(), cursor.getUpperBound(), cursor.getPos());
- }
- if (cursor.atEnd()) {
- throw new ParseException("Invalid protocol version",
- buffer, cursor.getLowerBound(), cursor.getUpperBound(), cursor.getPos());
- }
- cursor.updatePos(cursor.getPos() + 1);
- final String token2 = this.tokenizer.parseToken(buffer, cursor, BLANKS);
- final int minor;
- try {
- minor = Integer.parseInt(token2);
- } catch (final NumberFormatException e) {
- throw new ParseException("Invalid protocol minor version number",
- buffer, cursor.getLowerBound(), cursor.getUpperBound(), cursor.getPos());
- }
- return HttpVersion.get(major, minor);
+ return ProtocolVersionParser.INSTANCE.parse(protoname, HttpVersion::get, buffer, cursor, null);
}
/**
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/ssl/TLS.java b/httpcore5/src/main/java/org/apache/hc/core5/http/ssl/TLS.java
index d1884f146..9a8021d9a 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/ssl/TLS.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/ssl/TLS.java
@@ -30,8 +30,10 @@
import java.util.ArrayList;
import java.util.List;
+import org.apache.hc.core5.annotation.Internal;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.ProtocolVersionParser;
import org.apache.hc.core5.util.Tokenizer;
/**
@@ -90,12 +92,41 @@ public boolean lessEquals(final ProtocolVersion protocolVersion) {
return version.lessEquals(protocolVersion);
}
+ @Internal
+ public static ProtocolVersion parse(
+ final CharSequence buffer,
+ final Tokenizer.Cursor cursor,
+ final Tokenizer.Delimiter delimiterPredicate) throws ParseException {
+ final int lowerBound = cursor.getLowerBound();
+ final int upperBound = cursor.getUpperBound();
+
+ int pos = cursor.getPos();
+ if (pos + 4 > cursor.getUpperBound()) {
+ throw new ParseException("Invalid TLS protocol version", buffer, lowerBound, upperBound, pos);
+ }
+ if (buffer.charAt(pos) != 'T' || buffer.charAt(pos + 1) != 'L' || buffer.charAt(pos + 2) != 'S'
+ || buffer.charAt(pos + 3) != 'v') {
+ throw new ParseException("Invalid TLS protocol version", buffer, lowerBound, upperBound, pos);
+ }
+ pos = pos + 4;
+ cursor.updatePos(pos);
+ if (cursor.atEnd()) {
+ throw new ParseException("Invalid TLS version", buffer, lowerBound, upperBound, pos);
+ }
+ return ProtocolVersionParser.INSTANCE.parse("TLS", null, buffer, cursor, delimiterPredicate);
+ }
+
public static ProtocolVersion parse(final String s) throws ParseException {
if (s == null) {
return null;
}
final Tokenizer.Cursor cursor = new Tokenizer.Cursor(0, s.length());
- return TlsVersionParser.INSTANCE.parse(s, cursor, null);
+ final ProtocolVersion protocolVersion = parse(s, cursor, null);
+ Tokenizer.INSTANCE.skipWhiteSpace(s, cursor);
+ if (!cursor.atEnd()) {
+ throw new ParseException("Invalid TLS protocol version; trailing content");
+ }
+ return protocolVersion;
}
public static String[] excludeWeak(final String... protocols) {
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/ssl/TlsVersionParser.java b/httpcore5/src/main/java/org/apache/hc/core5/http/ssl/TlsVersionParser.java
deleted file mode 100644
index 296e5f814..000000000
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/ssl/TlsVersionParser.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
- *
- */
-
-package org.apache.hc.core5.http.ssl;
-
-import org.apache.hc.core5.http.ParseException;
-import org.apache.hc.core5.http.ProtocolVersion;
-import org.apache.hc.core5.util.Tokenizer;
-
-final class TlsVersionParser {
-
- public final static TlsVersionParser INSTANCE = new TlsVersionParser();
-
- private final Tokenizer tokenizer;
-
- TlsVersionParser() {
- this.tokenizer = Tokenizer.INSTANCE;
- }
-
- ProtocolVersion parse(
- final CharSequence buffer,
- final Tokenizer.Cursor cursor,
- final Tokenizer.Delimiter delimiterPredicate) throws ParseException {
- final int lowerBound = cursor.getLowerBound();
- final int upperBound = cursor.getUpperBound();
-
- int pos = cursor.getPos();
- if (pos + 4 > cursor.getUpperBound()) {
- throw new ParseException("Invalid TLS protocol version", buffer, lowerBound, upperBound, pos);
- }
- if (buffer.charAt(pos) != 'T' || buffer.charAt(pos + 1) != 'L' || buffer.charAt(pos + 2) != 'S'
- || buffer.charAt(pos + 3) != 'v') {
- throw new ParseException("Invalid TLS protocol version", buffer, lowerBound, upperBound, pos);
- }
- pos = pos + 4;
- cursor.updatePos(pos);
- if (cursor.atEnd()) {
- throw new ParseException("Invalid TLS version", buffer, lowerBound, upperBound, pos);
- }
- final String s = this.tokenizer.parseToken(buffer, cursor, delimiterPredicate);
- final int idx = s.indexOf('.');
- if (idx == -1) {
- final int major;
- try {
- major = Integer.parseInt(s);
- } catch (final NumberFormatException e) {
- throw new ParseException("Invalid TLS major version", buffer, lowerBound, upperBound, pos);
- }
- return new ProtocolVersion("TLS", major, 0);
- } else {
- final String s1 = s.substring(0, idx);
- final int major;
- try {
- major = Integer.parseInt(s1);
- } catch (final NumberFormatException e) {
- throw new ParseException("Invalid TLS major version", buffer, lowerBound, upperBound, pos);
- }
- final String s2 = s.substring(idx + 1);
- final int minor;
- try {
- minor = Integer.parseInt(s2);
- } catch (final NumberFormatException e) {
- throw new ParseException("Invalid TLS minor version", buffer, lowerBound, upperBound, pos);
- }
- return new ProtocolVersion("TLS", major, minor);
- }
- }
-
- ProtocolVersion parse(final String s) throws ParseException {
- if (s == null) {
- return null;
- }
- final Tokenizer.Cursor cursor = new Tokenizer.Cursor(0, s.length());
- return parse(s, cursor, null);
- }
-
-}
-
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/TestProtocolVersion.java b/httpcore5/src/test/java/org/apache/hc/core5/http/TestProtocolVersion.java
index 827e0a336..1701ccc35 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/TestProtocolVersion.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/TestProtocolVersion.java
@@ -27,6 +27,10 @@
package org.apache.hc.core5.http;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.apache.hc.core5.util.Tokenizer;
+import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -45,4 +49,31 @@ public void testEqualsMajorMinor() {
Assertions.assertFalse(PROTOCOL_VERSION_1_2.equals(2, 0));
}
+ @Test
+ public void testParseBasic() throws Exception {
+ assertThat(ProtocolVersion.parse("PROTO/1"), CoreMatchers.equalTo(new ProtocolVersion("PROTO", 1, 0)));
+ assertThat(ProtocolVersion.parse("PROTO/1.1"), CoreMatchers.equalTo(new ProtocolVersion("PROTO", 1, 1)));
+ assertThat(ProtocolVersion.parse("PROTO/1.2"), CoreMatchers.equalTo(new ProtocolVersion("PROTO", 1, 2)));
+ assertThat(ProtocolVersion.parse("PROTO/1.3 "), CoreMatchers.equalTo(new ProtocolVersion("PROTO", 1, 3)));
+ assertThat(ProtocolVersion.parse("PROTO/000.0000 "), CoreMatchers.equalTo(new ProtocolVersion("PROTO", 0, 0)));
+ assertThat(ProtocolVersion.parse("PROTO/22.356"), CoreMatchers.equalTo(new ProtocolVersion("PROTO", 22, 356)));
+ }
+
+ @Test
+ public void testParseBuffer() throws Exception {
+ final Tokenizer.Cursor cursor = new Tokenizer.Cursor(1, 13);
+ assertThat(ProtocolVersion.parse(" PROTO/1.2,0000", cursor, Tokenizer.delimiters(',')), CoreMatchers.equalTo(new ProtocolVersion("PROTO", 1, 2)));
+ assertThat(cursor.getPos(), CoreMatchers.equalTo(10));
+ }
+
+ @Test
+ public void testParseFailure() throws Exception {
+ Assertions.assertThrows(ParseException.class, () -> ProtocolVersion.parse("/1"));
+ Assertions.assertThrows(ParseException.class, () -> ProtocolVersion.parse(" /1"));
+ Assertions.assertThrows(ParseException.class, () -> ProtocolVersion.parse("PROTO/"));
+ Assertions.assertThrows(ParseException.class, () -> ProtocolVersion.parse("PROTO/1A"));
+ Assertions.assertThrows(ParseException.class, () -> ProtocolVersion.parse("PROTO/1.A"));
+ Assertions.assertThrows(ParseException.class, () -> ProtocolVersion.parse("PROTO/1.1 huh?"));
+ }
+
}
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/TestProtocolVersionParser.java b/httpcore5/src/test/java/org/apache/hc/core5/http/TestProtocolVersionParser.java
new file mode 100644
index 000000000..0cbddcfa5
--- /dev/null
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/TestProtocolVersionParser.java
@@ -0,0 +1,117 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+package org.apache.hc.core5.http;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.apache.hc.core5.http.message.ParserCursor;
+import org.apache.hc.core5.util.Tokenizer;
+import org.hamcrest.CoreMatchers;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Unit tests for {@link ProtocolVersionParser}.
+ */
+public class TestProtocolVersionParser {
+
+ private ProtocolVersionParser impl;
+
+ @BeforeEach
+ public void setup() {
+ impl = new ProtocolVersionParser();
+ }
+
+ public ProtocolVersion parseStr(final String protocol, final String s) throws ParseException {
+ return impl.parse(protocol, null, s, new ParserCursor(0, s.length()), null);
+ }
+
+ public ProtocolVersion parseStr(final String protocol, final String s, final Tokenizer.Delimiter delimiterPredicate) throws ParseException {
+ return impl.parse(protocol, null, s, new ParserCursor(0, s.length()), delimiterPredicate);
+ }
+
+ public ProtocolVersion parseStr(final String protocol, final String s, final Tokenizer.Cursor cursor, final Tokenizer.Delimiter delimiterPredicate) throws ParseException {
+ return impl.parse(protocol, null, s, cursor, delimiterPredicate);
+ }
+
+ public ProtocolVersion parseStr(final String s) throws ParseException {
+ return impl.parse(s, new ParserCursor(0, s.length()), null);
+ }
+
+ public ProtocolVersion parseStr(final String s, final Tokenizer.Delimiter delimiterPredicate) throws ParseException {
+ return impl.parse(s, new ParserCursor(0, s.length()), delimiterPredicate);
+ }
+
+ @Test
+ public void testParseVersion() throws Exception {
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 1, 0), parseStr("PROTO", "1 "));
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 1, 1), parseStr("PROTO", "1.1 "));
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 1, 20), parseStr("PROTO", "1.020 "));
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 22, 356), parseStr("PROTO", "22.356 "));
+
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 1, 0), parseStr("PROTO", "1, ", Tokenizer.delimiters(',')));
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 1, 1), parseStr("PROTO", "1.1; ", Tokenizer.delimiters(',', ';')));
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 1, 200), parseStr("PROTO", "1.200 blah; ", Tokenizer.delimiters(',')));
+ }
+
+ @Test
+ public void testParseVersionWithCursor() throws Exception {
+ final Tokenizer.Cursor cursor = new Tokenizer.Cursor(2, 13);
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 1, 20), parseStr("PROTO", " 1.20,0000,00000", cursor, Tokenizer.delimiters(',')));
+ assertThat(cursor.getPos(), CoreMatchers.equalTo(6));
+ }
+
+ @Test
+ public void testParseProtocolVersion() throws Exception {
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 1, 0), parseStr("PROTO/1 "));
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 1, 1), parseStr("PROTO/1.1 "));
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 1, 20), parseStr("PROTO/1.020 "));
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 22, 356), parseStr("PROTO/22.356 "));
+
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 1, 0), parseStr("PROTO/1, ", Tokenizer.delimiters(',')));
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 1, 1), parseStr("PROTO/1.1; ", Tokenizer.delimiters(',', ';')));
+ Assertions.assertEquals(new ProtocolVersion("PROTO", 1, 200), parseStr("PROTO/1.200 blah; ", Tokenizer.delimiters(',')));
+ }
+
+ @Test
+ public void testParseFailures() throws Exception {
+ Assertions.assertThrows(ParseException.class, () -> parseStr("PROTO", "blah"));
+ Assertions.assertThrows(ParseException.class, () -> parseStr("PROTO", "1.blah"));
+ Assertions.assertThrows(ParseException.class, () -> parseStr("PROTO", "1A.0"));
+ Assertions.assertThrows(ParseException.class, () -> parseStr("PROTO", ""));
+ Assertions.assertThrows(ParseException.class, () -> parseStr(""));
+ Assertions.assertThrows(ParseException.class, () -> parseStr(" "));
+ Assertions.assertThrows(ParseException.class, () -> parseStr(" /1.0"));
+ Assertions.assertThrows(ParseException.class, () -> parseStr(" / "));
+ Assertions.assertThrows(ParseException.class, () -> parseStr("PROTO"));
+ Assertions.assertThrows(ParseException.class, () -> parseStr("PROTO/"));
+ Assertions.assertThrows(ParseException.class, () -> parseStr("PROTO/ 1.0"));
+ }
+
+}
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/message/TestBasicLineParser.java b/httpcore5/src/test/java/org/apache/hc/core5/http/message/TestBasicLineParser.java
index afc431708..5037bda34 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/message/TestBasicLineParser.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/message/TestBasicLineParser.java
@@ -31,6 +31,7 @@
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.Method;
import org.apache.hc.core5.http.ParseException;
+import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.util.CharArrayBuffer;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@@ -198,9 +199,9 @@ public void testSLParseFailure() throws Exception {
public void testHttpVersionParsing() throws Exception {
final CharArrayBuffer buffer = new CharArrayBuffer(16);
buffer.append("HTTP/1.1");
- ParserCursor cursor = new ParserCursor(0, buffer.length());
+ final ParserCursor cursor = new ParserCursor(0, buffer.length());
- HttpVersion version = (HttpVersion) parser.parseProtocolVersion(buffer, cursor);
+ final ProtocolVersion version = parser.parseProtocolVersion(buffer, cursor);
Assertions.assertEquals("HTTP", version.getProtocol(), "HTTP protocol name");
Assertions.assertEquals(1, version.getMajor(), "HTTP major version number");
Assertions.assertEquals(1, version.getMinor(), "HTTP minor version number");
@@ -210,16 +211,16 @@ public void testHttpVersionParsing() throws Exception {
buffer.clear();
buffer.append("HTTP/1.123 123");
- cursor = new ParserCursor(0, buffer.length());
+ final ParserCursor cursor2 = new ParserCursor(0, buffer.length());
- version = (HttpVersion) parser.parseProtocolVersion(buffer, cursor);
- Assertions.assertEquals( "HTTP", version.getProtocol(), "HTTP protocol name");
- Assertions.assertEquals( 1, version.getMajor(), "HTTP major version number");
- Assertions.assertEquals(123, version.getMinor(), "HTTP minor version number");
- Assertions.assertEquals("HTTP/1.123", version.toString(), "HTTP version number");
- Assertions.assertEquals(' ', buffer.charAt(cursor.getPos()));
- Assertions.assertEquals(buffer.length() - 4, cursor.getPos());
- Assertions.assertFalse(cursor.atEnd());
+ final ProtocolVersion version2 = parser.parseProtocolVersion(buffer, cursor2);
+ Assertions.assertEquals( "HTTP", version2.getProtocol(), "HTTP protocol name");
+ Assertions.assertEquals( 1, version2.getMajor(), "HTTP major version number");
+ Assertions.assertEquals(123, version2.getMinor(), "HTTP minor version number");
+ Assertions.assertEquals("HTTP/1.123", version2.toString(), "HTTP version number");
+ Assertions.assertEquals(' ', buffer.charAt(cursor2.getPos()));
+ Assertions.assertEquals(buffer.length() - 4, cursor2.getPos());
+ Assertions.assertFalse(cursor2.atEnd());
}
@Test
@@ -251,11 +252,6 @@ public void testInvalidHttpVersionParsing() throws Exception {
Assertions.assertThrows(ParseException.class, () ->
parser.parseProtocolVersion(buffer, cursor5));
buffer.clear();
- buffer.append("HTTP/1234");
- final ParserCursor cursor6 = new ParserCursor(0, buffer.length());
- Assertions.assertThrows(ParseException.class, () ->
- parser.parseProtocolVersion(buffer, cursor6));
- buffer.clear();
buffer.append("HTTP/1.");
final ParserCursor cursor7 = new ParserCursor(0, buffer.length());
Assertions.assertThrows(ParseException.class, () ->
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/ssl/TLSTest.java b/httpcore5/src/test/java/org/apache/hc/core5/http/ssl/TLSTest.java
index e9a2730a4..23eb55801 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/ssl/TLSTest.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/ssl/TLSTest.java
@@ -27,10 +27,14 @@
package org.apache.hc.core5.http.ssl;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.apache.hc.core5.http.ParseException;
+import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.util.Tokenizer;
+import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -86,4 +90,32 @@ void excludeWeak() {
Assertions.assertTrue(TLS.isSecure(protocol));
}
}
+
+ @Test
+ public void testParseBasic() throws Exception {
+ assertThat(TLS.parse("TLSv1"), CoreMatchers.equalTo(TLS.V_1_0.getVersion()));
+ assertThat(TLS.parse("TLSv1.1"), CoreMatchers.equalTo(TLS.V_1_1.getVersion()));
+ assertThat(TLS.parse("TLSv1.2"), CoreMatchers.equalTo(TLS.V_1_2.getVersion()));
+ assertThat(TLS.parse("TLSv1.3 "), CoreMatchers.equalTo(TLS.V_1_3.getVersion()));
+ assertThat(TLS.parse("TLSv22.356"), CoreMatchers.equalTo(new ProtocolVersion("TLS", 22, 356)));
+ }
+
+ @Test
+ public void testParseBuffer() throws Exception {
+ final Tokenizer.Cursor cursor = new Tokenizer.Cursor(1, 13);
+ assertThat(TLS.parse(" TLSv1.2,0000", cursor, Tokenizer.delimiters(',')),
+ CoreMatchers.equalTo(TLS.V_1_2.getVersion()));
+ assertThat(cursor.getPos(), CoreMatchers.equalTo(8));
+ }
+
+ @Test
+ public void testParseFailure() throws Exception {
+ Assertions.assertThrows(ParseException.class, () -> TLS.parse("Tlsv1"));
+ Assertions.assertThrows(ParseException.class, () -> TLS.parse("TLSV1"));
+ Assertions.assertThrows(ParseException.class, () -> TLS.parse("TLSv"));
+ Assertions.assertThrows(ParseException.class, () -> TLS.parse("TLSv1A"));
+ Assertions.assertThrows(ParseException.class, () -> TLS.parse("TLSv1.A"));
+ Assertions.assertThrows(ParseException.class, () -> TLS.parse("TLSv1.1 huh?"));
+ }
+
}
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/ssl/TestTlsVersionParser.java b/httpcore5/src/test/java/org/apache/hc/core5/http/ssl/TestTlsVersionParser.java
deleted file mode 100644
index df9bf543e..000000000
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/ssl/TestTlsVersionParser.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
- *
- */
-
-package org.apache.hc.core5.http.ssl;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-
-import org.apache.hc.core5.http.ParseException;
-import org.apache.hc.core5.http.ProtocolVersion;
-import org.apache.hc.core5.util.Tokenizer;
-import org.hamcrest.CoreMatchers;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-/**
- * Unit tests for {@link TlsVersionParser}.
- */
-public class TestTlsVersionParser {
-
- private TlsVersionParser impl;
-
- @BeforeEach
- public void setup() {
- impl = new TlsVersionParser();
- }
-
- @Test
- public void testParseBasic() throws Exception {
- assertThat(impl.parse("TLSv1"), CoreMatchers.equalTo(TLS.V_1_0.getVersion()));
- assertThat(impl.parse("TLSv1.1"), CoreMatchers.equalTo(TLS.V_1_1.getVersion()));
- assertThat(impl.parse("TLSv1.2"), CoreMatchers.equalTo(TLS.V_1_2.getVersion()));
- assertThat(impl.parse("TLSv1.3"), CoreMatchers.equalTo(TLS.V_1_3.getVersion()));
- assertThat(impl.parse("TLSv22.356"), CoreMatchers.equalTo(new ProtocolVersion("TLS", 22, 356)));
- }
-
- @Test
- public void testParseBuffer() throws Exception {
- final Tokenizer.Cursor cursor = new Tokenizer.Cursor(1, 13);
- assertThat(impl.parse(" TLSv1.2,0000", cursor, Tokenizer.delimiters(',')),
- CoreMatchers.equalTo(TLS.V_1_2.getVersion()));
- assertThat(cursor.getPos(), CoreMatchers.equalTo(8));
- }
-
- @Test
- public void testParseFailure1() throws Exception {
- Assertions.assertThrows(ParseException.class, () ->
- impl.parse("Tlsv1"));
- }
-
- @Test
- public void testParseFailure2() throws Exception {
- Assertions.assertThrows(ParseException.class, () ->
- impl.parse("TLSV1"));
- }
-
- @Test
- public void testParseFailure3() throws Exception {
- Assertions.assertThrows(ParseException.class, () ->
- impl.parse("TLSv"));
- }
-
- @Test
- public void testParseFailure4() throws Exception {
- Assertions.assertThrows(ParseException.class, () ->
- impl.parse("TLSv1A"));
- }
-
- @Test
- public void testParseFailure5() throws Exception {
- Assertions.assertThrows(ParseException.class, () ->
- impl.parse("TLSv1.A"));
- }
-
-}