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