package com.vtence.molecule.middlewares;
import com.vtence.molecule.Request;
import com.vtence.molecule.Response;
import java.io.PrintWriter;
import java.io.StringWriter;
import static com.vtence.molecule.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static com.vtence.molecule.http.MimeTypes.HTML;
public class Failsafe extends AbstractMiddleware {
public Failsafe() {}
public void handle(Request request, Response response) throws Exception {
try {
forward(request, response).rescue(this::failsafeResponse);
} catch (Throwable error) {
failsafeResponse(response, error);
}
}
private void failsafeResponse(Response response, Throwable error) {
response.status(INTERNAL_SERVER_ERROR);
response.contentType(HTML + "; charset=utf-8");
response.body(formatAsHtml(error));
response.done();
}
private String formatAsHtml(Throwable error) {
StringWriter html = new StringWriter();
PrintWriter buffer = new PrintWriter(html);
buffer.println("<html>");
buffer.println("<body>");
buffer.println("<h1>Oups!</h1>");
buffer.println("<h2>Sorry, an internal error occurred</h2>");
printFullStackTrace(buffer, error);
buffer.println("</body>");
buffer.println("</html>");
return html.toString();
}
private void printFullStackTrace(PrintWriter buffer, Throwable error) {
printErrorAndCause(buffer, error, false);
}
private void printErrorAndCause(PrintWriter buffer, Throwable error, boolean isCause) {
buffer.println("<p>");
buffer.printf(" <strong>%s%s</strong>", isCause ? "Caused by: " : "", error).println();
buffer.println("</p>");
buffer.println("<ul>");
for (StackTraceElement stackTraceElement : error.getStackTrace()) {
buffer.println(" <li>" + stackTraceElement.toString() + "</li>");
}
buffer.println("</ul>");
if (error.getCause() != null) {
buffer.println();
printErrorAndCause(buffer, error.getCause(), true);
}
}
}