Gitiles malfunctions in conjunction with jgit and guice because of a recent Guice bug fix. Work around the problem by parsing the URI directly, bypassing the unescaping performed by the getPathInfo method. This rest of this message is copied from https://gerrit-review.googlesource.com/#/c/60820/ : The fix for Guice issue #745[1] causes getPathInfo() within the GuiceFilter to return decoded values, eliminating the difference between "foo/bar" and "foo%2Fbar". This is in spec with the servlet standard, whose javadoc for getPathInfo[2] states that the return value be "decoded by the web container". Work around this by extracting the path part directly from the request URI, which is unmodified by the container. This is copying the Guice behavior prior to the bugfix. [1] https://github.com/google/guice/issues/745 [2] http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequest.html#getPathInfo() Change-Id: I7fdb291bda377dab6160599ee537962d5f60f1e8 Signed-off-by: David Pletcher <dpletcher@google.com>tags/v3.7.0.201502031740-rc1
} | } | ||||
} | } | ||||
/** | |||||
* Get the path info component of the request. The result is similar to | |||||
* {@link HttpServletRequest#getPathInfo()}, but URL-encoded characters are | |||||
* not decoded. | |||||
* | |||||
* @param req | |||||
* the incoming request. | |||||
* @return the same value as {@link HttpServletRequest#getPathInfo()}, but | |||||
* without decoding URL-encoded characters. | |||||
* @since 3.6 | |||||
*/ | |||||
public static String getEncodedPathInfo(HttpServletRequest req) { | |||||
return getEncodedPathInfo(req.getContextPath(), req.getServletPath(), | |||||
req.getRequestURI()); | |||||
} | |||||
/** | |||||
* Get the path info component of the request. The result is similar to | |||||
* {@link HttpServletRequest#getPathInfo()}, but URL-encoded characters are | |||||
* not decoded. | |||||
* | |||||
* @param contextPath | |||||
* the context path from the incoming request. | |||||
* @param servletPath | |||||
* the servlet path from the incoming request. | |||||
* @param requestUri | |||||
* the request URI from the incoming request. | |||||
* @return the same value as {@link HttpServletRequest#getPathInfo()}, but | |||||
* without decoding URL-encoded characters. | |||||
*/ | |||||
static String getEncodedPathInfo(String contextPath, String servletPath, | |||||
String requestUri) { | |||||
String pathInfo = requestUri.substring(contextPath.length()) | |||||
.replaceAll("/{2,}", "/"); | |||||
if (!pathInfo.startsWith(servletPath)) | |||||
return null; | |||||
pathInfo = pathInfo.substring(servletPath.length()); | |||||
if (pathInfo.isEmpty() && !servletPath.isEmpty()) | |||||
return null; | |||||
return pathInfo; | |||||
} | |||||
private static byte[] sendInit(byte[] content, | private static byte[] sendInit(byte[] content, | ||||
final HttpServletRequest req, final HttpServletResponse rsp) | final HttpServletRequest req, final HttpServletResponse rsp) | ||||
throws IOException { | throws IOException { |
import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||
import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||
import org.eclipse.jgit.http.server.ServletUtils; | |||||
/** | /** | ||||
* Selects requests by matching the URI against a regular expression. | * Selects requests by matching the URI against a regular expression. | ||||
* <p> | * <p> | ||||
} | } | ||||
boolean match(final HttpServletRequest req) { | boolean match(final HttpServletRequest req) { | ||||
final String pathInfo = req.getPathInfo(); | |||||
final String pathInfo = ServletUtils.getEncodedPathInfo(req); | |||||
return pathInfo != null && pattern.matcher(pathInfo).matches(); | return pathInfo != null && pattern.matcher(pathInfo).matches(); | ||||
} | } | ||||
@Override | @Override | ||||
void service(HttpServletRequest req, HttpServletResponse rsp) | void service(HttpServletRequest req, HttpServletResponse rsp) | ||||
throws ServletException, IOException { | throws ServletException, IOException { | ||||
final String reqInfo = req.getPathInfo(); | |||||
final String reqInfo = ServletUtils.getEncodedPathInfo(req); | |||||
if (reqInfo == null) { | if (reqInfo == null) { | ||||
rsp.sendError(SC_NOT_FOUND); | rsp.sendError(SC_NOT_FOUND); | ||||
return; | return; |
import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||
import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||
import org.eclipse.jgit.http.server.ServletUtils; | |||||
/** | /** | ||||
* Selects requests by matching the suffix of the URI. | * Selects requests by matching the suffix of the URI. | ||||
* <p> | * <p> | ||||
} | } | ||||
boolean match(final HttpServletRequest req) { | boolean match(final HttpServletRequest req) { | ||||
final String pathInfo = req.getPathInfo(); | |||||
final String pathInfo = ServletUtils.getEncodedPathInfo(req); | |||||
return pathInfo != null && pathInfo.endsWith(suffix); | return pathInfo != null && pathInfo.endsWith(suffix); | ||||
} | } | ||||
@Override | @Override | ||||
void service(HttpServletRequest req, HttpServletResponse rsp) | void service(HttpServletRequest req, HttpServletResponse rsp) | ||||
throws ServletException, IOException { | throws ServletException, IOException { | ||||
String curInfo = req.getPathInfo(); | |||||
String curInfo = ServletUtils.getEncodedPathInfo(req); | |||||
String newPath = req.getServletPath() + curInfo; | String newPath = req.getServletPath() + curInfo; | ||||
String newInfo = curInfo.substring(0, curInfo.length() - suffixLen); | String newInfo = curInfo.substring(0, curInfo.length() - suffixLen); | ||||
super.service(new WrappedRequest(req, newPath, newInfo), rsp); | super.service(new WrappedRequest(req, newPath, newInfo), rsp); |
import org.junit.Test; | import org.junit.Test; | ||||
import static org.junit.Assert.assertEquals; | |||||
public class ServletUtilsTest { | public class ServletUtilsTest { | ||||
@Test | |||||
public void emptyContextPath() { | |||||
assertEquals("/foo/bar", | |||||
ServletUtils.getEncodedPathInfo("", "/s", "/s/foo/bar")); | |||||
assertEquals("/foo%2Fbar", | |||||
ServletUtils.getEncodedPathInfo("", "/s", "/s/foo%2Fbar")); | |||||
} | |||||
public void slashContextPath() { | |||||
assertEquals("/foo/bar", | |||||
ServletUtils.getEncodedPathInfo("/", "/s", "/s/foo/bar")); | |||||
assertEquals("/foo%2Fbar", | |||||
ServletUtils.getEncodedPathInfo("/", "/s", "/s/foo%2Fbar")); | |||||
} | |||||
@Test | |||||
public void emptyServletPath() { | |||||
assertEquals("/foo/bar", | |||||
ServletUtils.getEncodedPathInfo("/c", "", "/c/foo/bar")); | |||||
assertEquals("/foo%2Fbar", | |||||
ServletUtils.getEncodedPathInfo("/c", "", "/c/foo%2Fbar")); | |||||
} | |||||
@Test | |||||
public void trailingSlashes() { | |||||
assertEquals("/foo/bar/", | |||||
ServletUtils.getEncodedPathInfo("/c", "/s", "/c/s/foo/bar/")); | |||||
assertEquals("/foo/bar/", | |||||
ServletUtils.getEncodedPathInfo("/c", "/s", "/c/s/foo/bar///")); | |||||
assertEquals("/foo%2Fbar/", | |||||
ServletUtils.getEncodedPathInfo("/c", "/s", "/c/s/foo%2Fbar/")); | |||||
assertEquals("/foo%2Fbar/", ServletUtils.getEncodedPathInfo("/c", "/s", | |||||
"/c/s/foo%2Fbar///")); | |||||
} | |||||
@Test | |||||
public void servletPathMatchesRequestPath() { | |||||
assertEquals((String) null, | |||||
ServletUtils.getEncodedPathInfo("/c", "/s", "/c/s")); | |||||
} | |||||
@Test | @Test | ||||
public void testAcceptGzip() { | public void testAcceptGzip() { | ||||
assertFalse(ServletUtils.acceptsGzipEncoding((String) null)); | assertFalse(ServletUtils.acceptsGzipEncoding((String) null)); |
s.serveRegex("^(/c)(/d)$") | s.serveRegex("^(/c)(/d)$") | ||||
.through(new RegexGroupFilter(1)) | .through(new RegexGroupFilter(1)) | ||||
.with(new Servlet("test2")); | .with(new Servlet("test2")); | ||||
s.serveRegex("^(/e)/f(/g)$") | |||||
s.serveRegex("^(/e)/f.*(/g)$") | |||||
.through(new RegexGroupFilter(2)) | .through(new RegexGroupFilter(2)) | ||||
.with(new Servlet("test3")); | .with(new Servlet("test3")); | ||||
ctx.addServlet(new ServletHolder(s), "/*"); | ctx.addServlet(new ServletHolder(s), "/*"); | ||||
assertEquals("/c", r.readLine()); | assertEquals("/c", r.readLine()); | ||||
assertEquals(null, r.readLine()); | assertEquals(null, r.readLine()); | ||||
c = ((HttpURLConnection) uri.resolve("/e/f/g").toURL() | |||||
c = ((HttpURLConnection) uri.resolve("/e/f/+/g").toURL() | |||||
.openConnection()); | .openConnection()); | ||||
assertEquals(200, c.getResponseCode()); | assertEquals(200, c.getResponseCode()); | ||||
r = new BufferedReader(new InputStreamReader(c.getInputStream())); | r = new BufferedReader(new InputStreamReader(c.getInputStream())); | ||||
assertEquals("test3", r.readLine()); | assertEquals("test3", r.readLine()); | ||||
assertEquals("/e/f", r.readLine()); | |||||
assertEquals("/e/f/+", r.readLine()); | |||||
assertEquals("/g", r.readLine()); | assertEquals("/g", r.readLine()); | ||||
assertEquals(null, r.readLine()); | assertEquals(null, r.readLine()); | ||||
} | } |