private void onException(Throwable e, Response r, boolean mapped) {
    if (request.isTracingEnabled()) {
      Response.Status s = Response.Status.fromStatusCode(r.getStatus());
      if (s != null) {
        request.trace(
            String.format(
                "mapped exception to response: %s -> %d (%s)",
                ReflectionHelper.objectToString(e), r.getStatus(), s.getReasonPhrase()));
      } else {
        request.trace(
            String.format(
                "mapped exception to response: %s -> %d",
                ReflectionHelper.objectToString(e), r.getStatus()));
      }
    }

    if (!mapped && r.getStatus() >= 500) {
      logException(e, r, Level.SEVERE);
    } else if (LOGGER.isLoggable(Level.FINE)) {
      logException(e, r, Level.FINE);
    }

    setResponse(r);

    this.mappedThrowable = e;

    if (getEntity() != null && getHttpHeaders().getFirst(HttpHeaders.CONTENT_TYPE) == null) {
      Object m = request.getProperties().get(HttpMethodRule.CONTENT_TYPE_PROPERTY);
      if (m != null) {
        request.getProperties().remove(HttpMethodRule.CONTENT_TYPE_PROPERTY);
        getHttpHeaders().putSingle(HttpHeaders.CONTENT_TYPE, m);
      }
    }
  }
 private void logException(Throwable e, Response r, Level l) {
   Response.Status s = Response.Status.fromStatusCode(r.getStatus());
   if (s != null) {
     LOGGER.log(
         l,
         "Mapped exception to response: " + r.getStatus() + " (" + s.getReasonPhrase() + ")",
         e);
   } else {
     LOGGER.log(l, "Mapped exception to response: " + r.getStatus(), e);
   }
 }
Esempio n. 3
0
  /**
   * Receives standard HTTP requests from the public {@code service} method and dispatches them to
   * the {@code do}<i>XXX</i> methods defined in this class. This method is an HTTP-specific version
   * of the {@link javax.servlet.Servlet#service} method. There's no need to override this method.
   *
   * @param request the {@link HttpServletRequest} object that contains the request the client made
   *     of the servlet
   * @param response the {@link HttpServletResponse} object that contains the response the servlet
   *     returns to the client
   * @throws IOException if an input or output error occurs while the servlet is handling the HTTP
   *     request
   * @throws ServletException if the HTTP request cannot be handled
   * @see javax.servlet.Servlet#service
   */
  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    /**
     * There is an annoying edge case where the service method is invoked for the case when the URI
     * is equal to the deployment URL minus the '/', for example
     * http://locahost:8080/HelloWorldWebApp
     */
    final String servletPath = request.getServletPath();
    String pathInfo = request.getPathInfo();
    StringBuffer requestURL = request.getRequestURL();
    String requestURI = request.getRequestURI();
    final boolean checkPathInfo = pathInfo == null || pathInfo.isEmpty() || pathInfo.equals("/");
    if (checkPathInfo && !request.getRequestURI().endsWith("/")) {
      // Only do this if the last segment of the servlet path does not contain '.'
      // This handles the case when the extension mapping is used with the servlet
      // see issue 506
      // This solution does not require parsing the deployment descriptor,
      // however still leaves it broken for the very rare case if a standard path
      // servlet mapping would include dot in the last segment (e.g. /.webresources/*)
      // and somebody would want to hit the root resource without the trailing slash
      int i = servletPath.lastIndexOf('/');
      if (servletPath.substring(i + 1).indexOf('.') < 0) {
        // TODO (+ handle request URL with invalid characters - see the creation of
        // absoluteUriBuilder bellow)
        //                if
        // (webComponent.getResourceConfig().getFeature(ResourceConfig.FEATURE_REDIRECT)) {
        //                    URI l = UriBuilder.fromUri(request.getRequestURL().toString()).
        //                            path("/").
        //                            replaceQuery(request.getQueryString()).build();
        //
        //                    response.setStatus(307);
        //                    response.setHeader("Location", l.toASCIIString());
        //                    return;
        //                } else {
        //                pathInfo = "/";
        //                requestURL.append("/");
        //                requestURI += "/";
        //                }
      }
    }

    /**
     * The HttpServletRequest.getRequestURL() contains the complete URI minus the query and fragment
     * components.
     */
    UriBuilder absoluteUriBuilder;
    try {
      absoluteUriBuilder = UriBuilder.fromUri(requestURL.toString());
    } catch (IllegalArgumentException iae) {
      final Response.Status badRequest = Response.Status.BAD_REQUEST;
      if (webComponent.configSetStatusOverSendError) {
        response.reset();
        response.setStatus(badRequest.getStatusCode(), badRequest.getReasonPhrase());
      } else {
        response.sendError(badRequest.getStatusCode(), badRequest.getReasonPhrase());
      }
      return;
    }

    /**
     * The HttpServletRequest.getPathInfo() and HttpServletRequest.getServletPath() are in decoded
     * form.
     *
     * <p>On some servlet implementations the getPathInfo() removed contiguous '/' characters. This
     * is problematic if URIs are embedded, for example as the last path segment. We need to work
     * around this and not use getPathInfo for the decodedPath.
     */
    final String decodedBasePath = request.getContextPath() + servletPath + "/";

    final String encodedBasePath = UriComponent.encode(decodedBasePath, UriComponent.Type.PATH);

    if (!decodedBasePath.equals(encodedBasePath)) {
      throw new ProcessingException(
          "The servlet context path and/or the "
              + "servlet path contain characters that are percent encoded");
    }

    final URI baseUri;
    final URI requestUri;
    try {
      baseUri = absoluteUriBuilder.replacePath(encodedBasePath).build();

      String queryParameters = request.getQueryString();
      if (queryParameters == null) {
        queryParameters = "";
      }

      requestUri = absoluteUriBuilder.replacePath(requestURI).replaceQuery(queryParameters).build();
    } catch (UriBuilderException ex) {
      final Response.Status badRequest = Response.Status.BAD_REQUEST;
      if (webComponent.configSetStatusOverSendError) {
        response.reset();
        response.setStatus(badRequest.getStatusCode(), badRequest.getReasonPhrase());
      } else {
        response.sendError(badRequest.getStatusCode(), badRequest.getReasonPhrase());
      }
      return;
    }

    service(baseUri, requestUri, request, response);
  }