Line data Source code
1 : // Copyright (C) 2014 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.util.http; 16 : 17 : import com.google.common.base.Splitter; 18 : import java.util.List; 19 : import javax.servlet.http.HttpServletRequest; 20 : 21 : /** Utilities for manipulating HTTP request objects. */ 22 : public class RequestUtil { 23 30 : private static final Splitter SPLITTER = Splitter.on("/"); 24 : 25 : /** HTTP request attribute for storing the Throwable that caused an error condition. */ 26 30 : private static final String ATTRIBUTE_ERROR_TRACE = 27 30 : RequestUtil.class.getName() + "/ErrorTraceThrowable"; 28 : 29 : public static void setErrorTraceAttribute(HttpServletRequest req, Throwable t) { 30 21 : req.setAttribute(ATTRIBUTE_ERROR_TRACE, t); 31 21 : } 32 : 33 : public static Throwable getErrorTraceAttribute(HttpServletRequest req) { 34 0 : return (Throwable) req.getAttribute(ATTRIBUTE_ERROR_TRACE); 35 : } 36 : 37 : /** 38 : * Returns the same value as {@link HttpServletRequest#getPathInfo()}, but without decoding 39 : * URL-encoded characters. 40 : */ 41 : public static String getEncodedPathInfo(HttpServletRequest req) { 42 : // CS IGNORE LineLength FOR NEXT 3 LINES. REASON: URL. 43 : // Based on com.google.guice.ServletDefinition$1#getPathInfo() from: 44 : // https://github.com/google/guice/blob/41c126f99d6309886a0ded2ac729033d755e1593/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java 45 29 : String servletPath = req.getServletPath(); 46 29 : int servletPathLength = servletPath.length(); 47 29 : String requestUri = req.getRequestURI(); 48 29 : String pathInfo = 49 29 : requestUri.substring(req.getContextPath().length()).replaceAll("[/]{2,}", "/"); 50 29 : if (pathInfo.startsWith(servletPath)) { 51 29 : pathInfo = pathInfo.substring(servletPathLength); 52 : // Corner case: when servlet path & request path match exactly (without 53 : // trailing '/'), then pathinfo is null. 54 29 : if (pathInfo.isEmpty() && servletPathLength > 0) { 55 7 : pathInfo = null; 56 : } 57 : } else { 58 0 : pathInfo = null; 59 : } 60 29 : return pathInfo; 61 : } 62 : 63 : /** 64 : * Trims leading '/' and 'a/'. Removes the context path, but keeps the servlet path. Removes all 65 : * IDs from the rest of the URI. 66 : * 67 : * <p>The returned string is a good fit for cases where one wants the full context of the request 68 : * without any identifiable data. For example: Logging or quota checks. 69 : * 70 : * <p>Examples: 71 : * 72 : * <ul> 73 : * <li>/a/accounts/self/detail => /accounts/detail 74 : * <li>/changes/123/revisions/current/detail => /changes/revisions/detail 75 : * <li>/changes/ => /changes 76 : * </ul> 77 : */ 78 : public static String getRestPathWithoutIds(HttpServletRequest req) { 79 29 : String encodedPathInfo = req.getRequestURI().substring(req.getContextPath().length()); 80 29 : if (encodedPathInfo.startsWith("/")) { 81 29 : encodedPathInfo = encodedPathInfo.substring(1); 82 : } 83 29 : if (encodedPathInfo.startsWith("a/")) { 84 29 : encodedPathInfo = encodedPathInfo.substring(2); 85 : } 86 : 87 29 : List<String> parts = SPLITTER.splitToList(encodedPathInfo); 88 29 : StringBuilder result = new StringBuilder(parts.size()); 89 29 : for (int i = 0; i < parts.size(); i = i + 2) { 90 29 : result.append("/"); 91 29 : result.append(parts.get(i)); 92 : } 93 29 : return result.toString(); 94 : } 95 : 96 : public static boolean acceptsGzipEncoding(HttpServletRequest request) { 97 1 : String accepts = request.getHeader("Accept-Encoding"); 98 1 : return accepts != null && accepts.indexOf("gzip") != -1; 99 : } 100 : 101 : private RequestUtil() {} 102 : }