/** * 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); }