All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.vertx.ext.web.handler.impl.ErrorHandlerImpl Maven / Gradle / Ivy

/*
 * Copyright 2014 Red Hat, Inc.
 *
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  and Apache License v2.0 which accompanies this distribution.
 *
 *  The Eclipse Public License is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  The Apache License v2.0 is available at
 *  http://www.opensource.org/licenses/apache2.0.php
 *
 *  You may elect to redistribute this code under either of these licenses.
 */

package io.vertx.ext.web.handler.impl;

import io.vertx.core.http.HttpHeaders;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.handler.ErrorHandler;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.impl.Utils;

import java.util.List;
import java.util.Objects;

/**
 * @author Paulo Lopes
 * @author Tim Fox
 */
public class ErrorHandlerImpl implements ErrorHandler {

  /**
   * Flag to enable/disable printing the full stack trace of exceptions.
   */
  private final boolean displayExceptionDetails;

  /**
   * Cached template for rendering the html errors
   */
  private final String errorTemplate;

  public ErrorHandlerImpl(String errorTemplateName, boolean displayExceptionDetails) {
    Objects.requireNonNull(errorTemplateName);
    this.displayExceptionDetails = displayExceptionDetails;
    this.errorTemplate = Utils.readResourceToBuffer(errorTemplateName).toString();
  }

  @Override
  public void handle(RoutingContext context) {

    HttpServerRequest request = context.request();
    HttpServerResponse response = context.response();

    if (context.statusCode() != -1) {
      response.setStatusCode(context.statusCode());
    } else {
      // Internal error
      response.setStatusCode(500);
    }

    // does the response already set the mime type?
    String mime = response.headers().get(HttpHeaders.CONTENT_TYPE);

    int errorCode;
    String errorMessage = null;
    if (context.statusCode() != -1) {
      errorCode = context.statusCode();
      errorMessage = context.response().getStatusMessage();
    } else {
      errorCode = 500;
      if (displayExceptionDetails) {
        errorMessage = context.failure().getMessage();
      }
      if (errorMessage == null) {
        errorMessage = "Internal Server Error";
      }
      // no new lines are allowed in the status message
      response.setStatusMessage(errorMessage.replaceAll("\\r|\\n", " "));
    }

    if (mime != null) {
      if (sendError(context, mime, errorCode, errorMessage)) {
        return;
      }
    }

    // respect the client accept order
    List acceptedMimes = Utils.getSortedAcceptableMimeTypes(request.headers().get(HttpHeaders.ACCEPT));

    for (String accept : acceptedMimes) {
      if (sendError(context, accept, errorCode, errorMessage)) {
        return;
      }
    }

    // fall back plain/text
    sendError(context, "text/plain", errorCode, errorMessage);
  }

  private boolean sendError(RoutingContext context, String mime, int errorCode, String errorMessage) {

    final String title = "Matron!";

    HttpServerResponse response = context.response();

    if (mime.startsWith("text/html")) {
      StringBuilder stack = new StringBuilder();
      if (context.failure() != null && displayExceptionDetails) {
        for (StackTraceElement elem: context.failure().getStackTrace()) {
          stack.append("
  • ").append(elem).append("
  • "); } } response.putHeader(HttpHeaders.CONTENT_TYPE,"text/html"); response.end( errorTemplate.replace("{title}", title) .replace("{errorCode}", Integer.toString(errorCode)) .replace("{errorMessage}", errorMessage) .replace("{stackTrace}", stack.toString()) ); return true; } if (mime.startsWith("application/json")) { JsonObject jsonError = new JsonObject(); jsonError.put("error", new JsonObject().put("code", errorCode).put("message", errorMessage)); if (context.failure() != null && displayExceptionDetails) { JsonArray stack = new JsonArray(); for (StackTraceElement elem: context.failure().getStackTrace()) { stack.add(elem.toString()); } jsonError.put("stack", stack); } response.putHeader(HttpHeaders.CONTENT_TYPE, "application/json"); response.end(jsonError.encode()); return true; } if (mime.startsWith("text/plain")) { response.putHeader(HttpHeaders.CONTENT_TYPE, "text/plain"); StringBuilder sb = new StringBuilder(); sb.append("Error "); sb.append(errorCode); sb.append(": "); sb.append(errorMessage); if (context.failure() != null && displayExceptionDetails) { for (StackTraceElement elem: context.failure().getStackTrace()) { sb.append("\tat ").append(elem).append("\n"); } } response.end(sb.toString()); return true; } return false; } }




    © 2015 - 2024 Weber Informatics LLC | Privacy Policy