diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index 6fe4a4ff8c3..177a9f79471 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -50,6 +50,7 @@ import org.eclipse.jetty.server.HttpChannelState.Action; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ErrorHandler; import org.eclipse.jetty.util.BlockingCallback; +import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.log.Log; @@ -672,7 +673,16 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable try { if (_state.handling()==Action.REQUEST_DISPATCH) - sendResponse(new ResponseInfo(HttpVersion.HTTP_1_1,new HttpFields(),0,status,reason,false),null,true); + { + ByteBuffer content=null; + HttpFields fields=new HttpFields(); + + ErrorHandler handler=getServer().getBean(ErrorHandler.class); + if (handler!=null) + content=handler.badMessageError(status,reason,fields); + + sendResponse(new ResponseInfo(HttpVersion.HTTP_1_1,fields,0,status,reason,false),content ,true); + } } catch (IOException e) { 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 b580cfc9670..3a79605d663 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 @@ -22,18 +22,22 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; +import java.nio.ByteBuffer; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.server.Dispatcher; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; +import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.ByteArrayISO8859Writer; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -42,7 +46,8 @@ import org.eclipse.jetty.util.log.Logger; /** Handler for Error pages * An ErrorHandler is registered with {@link ContextHandler#setErrorHandler(ErrorHandler)} or * {@link org.eclipse.jetty.server.Server#addBean(Object)}. - * It is called by the HttpResponse.sendError method to write a error page. + * It is called by the HttpResponse.sendError method to write a error page via {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)} + * or via {@link #badMessageError(int, String, HttpFields)} for bad requests for which a dispatch cannot be done. * */ public class ErrorHandler extends AbstractHandler @@ -191,7 +196,26 @@ public class ErrorHandler extends AbstractHandler } } - + /* ------------------------------------------------------------ */ + /** Bad Message Error body + *

Generate a error response body to be sent for a bad message. + * In this case there is something wrong with the request, so either + * a request cannot be built, or it is not safe to build a request. + * This method allows for a simple error page body to be returned + * and some response headers to be set. + * @param status The error code that will be sent + * @param reason The reason for the error code (may be null) + * @param fields The header fields that will be sent with the response. + * @return The content as a ByteBuffer, or null for no body. + */ + public ByteBuffer badMessageError(int status, String reason, HttpFields fields) + { + if (reason==null) + reason=HttpStatus.getMessage(status); + fields.put(HttpHeader.CONTENT_TYPE,MimeTypes.Type.TEXT_HTML_8859_1.asString()); + return BufferUtil.toBuffer("

Bad Message "+status+"

reason: "+reason+"
"); + } + /* ------------------------------------------------------------ */ /** Get the cacheControl. * @return the cacheControl header to set on error responses. diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java index 1a7f0d8311a..1e00625a4f4 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java @@ -41,6 +41,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.server.handler.ErrorHandler; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.StdErrLog; @@ -71,6 +72,7 @@ public class HttpConnectionTest connector.setIdleTimeout(500); server.addConnector(connector); server.setHandler(new DumpHandler()); + server.addBean(new ErrorHandler()); server.start(); } @@ -640,7 +642,8 @@ public class HttpConnectionTest request.append("\015\012"); response = connector.getResponses(request.toString()); - checkContains(response, offset, "HTTP/1.1 413"); + offset = checkContains(response, offset, "HTTP/1.1 413"); + checkContains(response, offset, "

Bad Message 413

reason: Request Entity Too Large
"); } @Test