diff --git a/jetty-server/pom.xml b/jetty-server/pom.xml index c1046a3a6ef..4a4f4874e8d 100644 --- a/jetty-server/pom.xml +++ b/jetty-server/pom.xml @@ -74,5 +74,11 @@ tests test + + org.eclipse.jetty + jetty-util-ajax + ${project.version} + test + diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java index 39ad8b7f9ac..4e7a245535b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java @@ -26,7 +26,12 @@ import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -449,23 +454,31 @@ public class ErrorHandler extends AbstractHandler private void writeErrorJson(HttpServletRequest request, PrintWriter writer, int code, String message) { - writer - .append("{\n") - .append(" url: \"").append(request.getRequestURI()).append("\",\n") - .append(" status: \"").append(Integer.toString(code)).append("\",\n") - .append(" message: ").append(QuotedStringTokenizer.quote(message)).append(",\n"); - Object servlet = request.getAttribute(Dispatcher.ERROR_SERVLET_NAME); - if (servlet != null) - writer.append("servlet: \"").append(servlet.toString()).append("\",\n"); Throwable cause = (Throwable)request.getAttribute(Dispatcher.ERROR_EXCEPTION); + Object servlet = request.getAttribute(Dispatcher.ERROR_SERVLET_NAME); + Map json = new HashMap<>(); + + json.put("url", request.getRequestURI()); + json.put("status", Integer.toString(code)); + json.put("message", message); + if (servlet != null) + { + json.put("servlet", servlet.toString()); + } int c = 0; while (cause != null) { - writer.append(" cause").append(Integer.toString(c++)).append(": ") - .append(QuotedStringTokenizer.quote(cause.toString())).append(",\n"); + json.put("cause" + c++, cause.toString()); cause = cause.getCause(); } - writer.append("}"); + + writer.append(json.entrySet().stream() + .map(e -> QuotedStringTokenizer.quote(e.getKey()) + + ":" + + QuotedStringTokenizer.quote((e.getValue()))) + .collect(Collectors.joining(",\n", "{\n", "\n}"))); + + } protected void writeErrorPageStacks(HttpServletRequest request, Writer writer) diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorHandlerTest.java index 1216bc06ac0..dcc30b1ff72 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorHandlerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorHandlerTest.java @@ -19,6 +19,8 @@ package org.eclipse.jetty.server; import java.io.IOException; +import java.util.Map; + import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; @@ -30,6 +32,7 @@ import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpTester; import org.eclipse.jetty.server.handler.AbstractHandler; +import org.eclipse.jetty.util.ajax.JSON; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -303,4 +306,25 @@ public class ErrorHandlerTest assertThat("Response status code", response.getStatus(), is(444)); } + + @Test + public void testJsonResponse() throws Exception + { + String rawResponse = connector.getResponse( + "GET /badmessage/444 HTTP/1.1\r\n" + + "Host: Localhost\r\n" + + "Accept: text/json\r\n" + + "\r\n"); + HttpTester.Response response = HttpTester.parseResponse(rawResponse); + + assertThat("Response status code", response.getStatus(), is(444)); + + System.out.println("response:" + response.getContent()); + + Map jo = (Map) JSON.parse(response.getContent()); + + assertThat("url field null", jo.get("url"), is(notNullValue())); + assertThat("status field null", jo.get("status"), is(notNullValue())); + assertThat("message field null", jo.get("message"), is(notNullValue())); + } }