diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/message/BasicListHeaderIterator.java b/httpcore5/src/main/java/org/apache/hc/core5/http/message/BasicListHeaderIterator.java
index 5cc1b7bb9..c70d5c80f 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/message/BasicListHeaderIterator.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/message/BasicListHeaderIterator.java
@@ -81,6 +81,13 @@ public BasicListHeaderIterator(final List extends Header> headers, final Strin
this.lastIndex = -1;
}
+ BasicListHeaderIterator(final List extends Header> headers, final int currentIndex, final String name) {
+ super();
+ this.allHeaders = headers;
+ this.headerName = name;
+ this.currentIndex = currentIndex;
+ }
+
/**
* Determines the index of the next header.
*
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/message/HeaderGroup.java b/httpcore5/src/main/java/org/apache/hc/core5/http/message/HeaderGroup.java
index 072ea7ca5..fe010b5ce 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/message/HeaderGroup.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/message/HeaderGroup.java
@@ -345,10 +345,19 @@ public int countHeaders(final String name) {
*
* @return iterator over this group of headers.
*
+ *
+ * IMPORTANT: please note that if the header group mutates while the
+ * iterator returned by this method still has pending elements
+ * the sequence of headers produced by such iterator is considered
+ * unstable and can be incorrect.
+ *
* @since 5.0
*/
@Override
public Iterator headerIterator() {
+ if (this.headers.isEmpty()) {
+ return NullHeaderIterator.INSTANCE;
+ }
return new BasicListHeaderIterator(this.headers, null);
}
@@ -360,10 +369,28 @@ public Iterator headerIterator() {
*
* @return iterator over some headers in this group.
*
+ *
+ * IMPORTANT: please note that if the header group mutates while the
+ * iterator returned by this method still has pending elements
+ * the sequence of headers produced by such iterator is considered
+ * unstable and can be incorrect.
+ *
* @since 5.0
*/
@Override
public Iterator headerIterator(final String name) {
+ if (this.headers.isEmpty()) {
+ return NullHeaderIterator.INSTANCE;
+ }
+ if (name != null) {
+ for (int i = 0; i < this.headers.size(); i++) {
+ final Header h = this.headers.get(i);
+ if (h.getName().equalsIgnoreCase(name)) {
+ return new BasicListHeaderIterator(this.headers, i, name);
+ }
+ }
+ return NullHeaderIterator.INSTANCE;
+ }
return new BasicListHeaderIterator(this.headers, name);
}
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/message/NullHeaderIterator.java b/httpcore5/src/main/java/org/apache/hc/core5/http/message/NullHeaderIterator.java
new file mode 100644
index 000000000..dc11c429f
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/message/NullHeaderIterator.java
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * 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.message;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.apache.hc.core5.http.Header;
+
+final class NullHeaderIterator implements Iterator {
+
+ final static NullHeaderIterator INSTANCE = new NullHeaderIterator();
+
+ @Override
+ public boolean hasNext() {
+ return false;
+ }
+
+ @Override
+ public Header next() throws NoSuchElementException {
+ throw new NoSuchElementException("Iteration already finished.");
+ }
+
+ @Override
+ public void remove() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Removing headers is not supported.");
+ }
+
+}
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/message/TestHeaderGroup.java b/httpcore5/src/test/java/org/apache/hc/core5/http/message/TestHeaderGroup.java
index 9c1b8f83e..21fa97de9 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/message/TestHeaderGroup.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/message/TestHeaderGroup.java
@@ -162,13 +162,49 @@ void testCondensedHeader() {
}
@Test
- void testIterator() {
+ void testEmptyListIterator() {
final HeaderGroup headergroup = new HeaderGroup();
final Iterator i = headergroup.headerIterator();
Assertions.assertNotNull(i);
Assertions.assertFalse(i.hasNext());
}
+ @Test
+ void testEmptyListIteratorByName() {
+ final HeaderGroup headergroup = new HeaderGroup();
+ final Iterator i = headergroup.headerIterator("some-header");
+ Assertions.assertNotNull(i);
+ Assertions.assertFalse(i.hasNext());
+ }
+
+ @Test
+ void testNonEmptyListIteratorByName() {
+ final HeaderGroup headergroup = new HeaderGroup();
+ headergroup.setHeaders(
+ new BasicHeader("a", "a-one"),
+ new BasicHeader("b", "b-one"),
+ new BasicHeader("a", "a-two"),
+ new BasicHeader("b", "b-two"),
+ new BasicHeader("b", "b-three"));
+ final Iterator it1 = headergroup.headerIterator("a");
+ Assertions.assertNotNull(it1);
+ Assertions.assertTrue(it1.hasNext());
+ Assertions.assertEquals("a-one", it1.next().getValue());
+ Assertions.assertTrue(it1.hasNext());
+ Assertions.assertEquals("a-two", it1.next().getValue());
+ Assertions.assertFalse(it1.hasNext());
+
+ final Iterator it2 = headergroup.headerIterator("b");
+ Assertions.assertNotNull(it2);
+ Assertions.assertTrue(it2.hasNext());
+ Assertions.assertEquals("b-one", it2.next().getValue());
+ Assertions.assertTrue(it2.hasNext());
+ Assertions.assertEquals("b-two", it2.next().getValue());
+ Assertions.assertTrue(it2.hasNext());
+ Assertions.assertEquals("b-three", it2.next().getValue());
+ Assertions.assertFalse(it2.hasNext());
+ }
+
@Test
void testHeaderRemove() {
final HeaderGroup headergroup = new HeaderGroup();