From c60259f52158e2fc7b09b5dc539c8ee719495f8d Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 26 Dec 2023 13:51:55 +0530 Subject: [PATCH] Use TreeMap to store headers --- .../java/org/jsoup/helper/HttpConnection.java | 58 +++++-------------- 1 file changed, 13 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/jsoup/helper/HttpConnection.java b/src/main/java/org/jsoup/helper/HttpConnection.java index e52c39433e..6324a80149 100644 --- a/src/main/java/org/jsoup/helper/HttpConnection.java +++ b/src/main/java/org/jsoup/helper/HttpConnection.java @@ -44,6 +44,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; import java.util.zip.Inflater; @@ -51,7 +52,6 @@ import static org.jsoup.Connection.Method.HEAD; import static org.jsoup.helper.DataUtil.UTF_8; -import static org.jsoup.internal.Normalizer.lowerCase; /** * Implementation of {@link Connection}. @@ -410,18 +410,18 @@ private static abstract class Base> implements Conn Map cookies; private Base() { - headers = new LinkedHashMap<>(); + headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); cookies = new LinkedHashMap<>(); } private Base(Base copy) { + this(); url = copy.url; // unmodifiable object method = copy.method; - headers = new LinkedHashMap<>(); for (Map.Entry> entry : copy.headers.entrySet()) { headers.put(entry.getKey(), new ArrayList<>(entry.getValue())); } - cookies = new LinkedHashMap<>(); cookies.putAll(copy.cookies); // just holds strings + cookies.putAll(copy.cookies); // just holds strings } @Override @@ -453,8 +453,8 @@ public T method(Method method) { @Override public String header(String name) { Validate.notNullParam(name, "name"); - List vals = getHeadersCaseInsensitive(name); - if (vals.size() > 0) { + List vals = headers.get(name); + if (vals != null) { // https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 return StringUtil.join(vals, ", "); } @@ -465,15 +465,9 @@ public String header(String name) { @Override public T addHeader(String name, @Nullable String value) { Validate.notEmptyParam(name, "name"); - //noinspection ConstantConditions - value = value == null ? "" : value; - List values = headers(name); - if (values.isEmpty()) { - values = new ArrayList<>(); - headers.put(name, values); - } - values.add(value); + headers.computeIfAbsent(name, Functions.listFunction()) + .add(value == null ? "" : value); return (T) this; } @@ -481,7 +475,7 @@ public T addHeader(String name, @Nullable String value) { @Override public List headers(String name) { Validate.notEmptyParam(name, "name"); - return getHeadersCaseInsensitive(name); + return headers.getOrDefault(name, Collections.emptyList()); } @Override @@ -495,7 +489,7 @@ public T header(String name, String value) { @Override public boolean hasHeader(String name) { Validate.notEmptyParam(name, "name"); - return !getHeadersCaseInsensitive(name).isEmpty(); + return headers.containsKey(name); } /** @@ -505,20 +499,14 @@ public boolean hasHeader(String name) { public boolean hasHeaderWithValue(String name, String value) { Validate.notEmpty(name); Validate.notEmpty(value); - List values = headers(name); - for (String candidate : values) { - if (value.equalsIgnoreCase(candidate)) - return true; - } - return false; + return headers.getOrDefault(name, Collections.emptyList()).stream() + .anyMatch(value::equalsIgnoreCase); } @Override public T removeHeader(String name) { Validate.notEmptyParam(name, "name"); - Map.Entry> entry = scanHeaders(name); // remove is case-insensitive too - if (entry != null) - headers.remove(entry.getKey()); // ensures correct case + headers.remove(name); // remove is case-insensitive too return (T) this; } @@ -539,26 +527,6 @@ public Map> multiHeaders() { return headers; } - private List getHeadersCaseInsensitive(String name) { - Validate.notNull(name); - - for (Map.Entry> entry : headers.entrySet()) { - if (name.equalsIgnoreCase(entry.getKey())) - return entry.getValue(); - } - - return Collections.emptyList(); - } - - private Map.@Nullable Entry> scanHeaders(String name) { - String lc = lowerCase(name); - for (Map.Entry> entry : headers.entrySet()) { - if (lowerCase(entry.getKey()).equals(lc)) - return entry; - } - return null; - } - @Override public String cookie(String name) { Validate.notEmptyParam(name, "name");