diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Fields.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Fields.java index f0015c70d0a..b0a2842ea21 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Fields.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Fields.java @@ -329,7 +329,14 @@ public Iterator iterator() */ public Map toStringArrayMap() { - Map result = new LinkedHashMap<>(); + Map result = new LinkedHashMap<>() + { + @Override + public String toString() + { + return TypeUtil.toString(this); + } + }; fields.forEach((k, f) -> result.put(f.getName(), f.getValues().toArray(new String[0]))); return result; } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/MultiMap.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/MultiMap.java index f9ce0f22a8c..8a43a4325d3 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/MultiMap.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/MultiMap.java @@ -15,7 +15,6 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -330,33 +329,7 @@ public boolean containsSimpleValue(V value) @Override public String toString() { - Iterator>> iter = entrySet().iterator(); - StringBuilder sb = new StringBuilder(); - sb.append('{'); - boolean delim = false; - while (iter.hasNext()) - { - Map.Entry> e = iter.next(); - if (delim) - { - sb.append(", "); - } - String key = e.getKey(); - List vals = e.getValue(); - sb.append(key); - sb.append('='); - if (vals.size() == 1) - { - sb.append(vals.get(0)); - } - else - { - sb.append(vals); - } - delim = true; - } - sb.append('}'); - return sb.toString(); + return TypeUtil.toString(this); } /** diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java index 7d0bdb94331..995f5107285 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java @@ -35,6 +35,7 @@ import java.util.Iterator; import java.util.List; import java.util.ListIterator; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.ServiceConfigurationError; @@ -864,4 +865,39 @@ public static boolean isDeclaredMethodOn(Object object, String methodName, Class return false; } } + + /** + * Pretty print a map. Specifically expanding Array values. + * @param map The map to render as a String + * @return A String representation of the map + */ + public static String toString(Map map) + { + if (map.isEmpty()) + return "{}"; + + StringBuilder sb = new StringBuilder(); + sb.append('{'); + for (Iterator> i = map.entrySet().iterator(); i.hasNext();) + { + Map.Entry e = i.next(); + Object key = e.getKey(); + sb.append(key); + sb.append('='); + + Object value = e.getValue(); + + if (value == null) + sb.append("null"); + else if (value.getClass().isArray()) + sb.append(Arrays.asList((Object[])value)); + else + sb.append(value); + if (i.hasNext()) + sb.append(','); + } + sb.append('}'); + return sb.toString(); + } + } diff --git a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/MultiMapTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/MultiMapTest.java index 45a430b714d..fd2a350cfa1 100644 --- a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/MultiMapTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/MultiMapTest.java @@ -462,12 +462,12 @@ public void testToString() MultiMap mm = new MultiMap<>(); mm.put("color", "red"); - assertEquals("{color=red}", mm.toString()); + assertEquals("{color=[red]}", mm.toString()); mm.putValues("food", "apple", "cherry", "raspberry"); - String expected1 = "{color=red, food=[apple, cherry, raspberry]}"; - String expected2 = "{food=[apple, cherry, raspberry], color=red}"; + String expected1 = "{color=[red],food=[apple, cherry, raspberry]}"; + String expected2 = "{food=[apple, cherry, raspberry],color=[red]}"; String actual = mm.toString(); assertTrue(actual.equals(expected1) || actual.equals(expected2)); } diff --git a/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/RequestTest.java b/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/RequestTest.java index 69d820b4d52..4ee3dac98e9 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/RequestTest.java +++ b/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/RequestTest.java @@ -16,6 +16,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.Socket; @@ -626,4 +627,49 @@ protected void service(HttpServletRequest request, HttpServletResponse resp) thr assertThat(date, containsString(":")); } } + + @Test + public void testParameters() throws Exception + { + final AtomicReference parameterMap = new AtomicReference<>(); + + startServer(new HttpServlet() + { + @Override + protected void service(HttpServletRequest request, HttpServletResponse resp) throws IOException + { + parameterMap.set(request.getParameterMap().toString()); + PrintWriter out = resp.getWriter(); + out.println(request.getParameter("a")); + out.println(request.getParameterValues("a")[1]); + out.println(request.getParameterValues("a")[2]); + out.println(Arrays.asList(request.getParameterValues("b"))); + out.println(Arrays.asList(request.getParameterValues("c"))); + out.println(Arrays.asList(request.getParameterValues("d"))); + + } + }); + + String rawResponse = _connector.getResponse( + """ + POST /test/parameters?a=1&a=2&b=one&c= HTTP/1.1\r + Host: localhost\r + Connection: close\r + Content-Type: application/x-www-form-urlencoded\r + Content-Length: 23\r + \r + a=3&b=two&b=three&d=xyz\r + """); + HttpTester.Response response = HttpTester.parseResponse(rawResponse); + assertThat(response.getStatus(), is(HttpStatus.OK_200)); + assertThat(parameterMap.get(), is("{a=[1, 2, 3],b=[one, two, three],c=[],d=[xyz]}")); + assertThat(response.getContent().replaceAll("\r\n", "\n"), is(""" + 1 + 2 + 3 + [one, two, three] + [] + [xyz] + """)); + } }