Correctly redirect legacy URIs with any final segment URIs like `/c/1/123`, `/c/1/1..3` or ``/c/1/anyThing` currently returns a 404. The legacy format, without project name in the URI, is not correctly handled. Handle it in the backend. Bug: Issue 346377876 Bug: Issue 346618792 Release-Notes: skip Change-Id: Id9fff1923a9c6e5cb3cbc458af5fbb9f0dd23af9
diff --git a/java/com/google/gerrit/httpd/NumericChangeIdRedirectServlet.java b/java/com/google/gerrit/httpd/NumericChangeIdRedirectServlet.java index 48dcea2..2c80c9b 100644 --- a/java/com/google/gerrit/httpd/NumericChangeIdRedirectServlet.java +++ b/java/com/google/gerrit/httpd/NumericChangeIdRedirectServlet.java
@@ -14,6 +14,9 @@ package com.google.gerrit.httpd; +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.google.common.collect.ImmutableList; import com.google.gerrit.common.PageLinks; import com.google.gerrit.entities.Change; import com.google.gerrit.extensions.restapi.ResourceConflictException; @@ -24,6 +27,7 @@ import com.google.inject.Inject; import com.google.inject.Singleton; import java.io.IOException; +import java.util.Arrays; import java.util.Optional; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -54,13 +58,13 @@ @Override protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException { String uriPath = req.getPathInfo(); - // Check if we are processing a comment url, like "/c/1/comment/ff3303fd_8341647b/". - int commentIdx = uriPath.indexOf("/comment"); - String idString = commentIdx == -1 ? uriPath : uriPath.substring(0, commentIdx); - if (idString.endsWith("/")) { - idString = idString.substring(0, idString.length() - 1); - } + ImmutableList<String> uriSegments = + Arrays.stream(uriPath.split("/", 2)).collect(toImmutableList()); + + String idString = uriSegments.get(0); + String finalSegment = (uriSegments.size() > 1) ? uriSegments.get(1) : null; + Optional<Change.Id> id = Change.Id.tryParse(idString); if (id.isEmpty()) { rsp.sendError(HttpServletResponse.SC_NOT_FOUND); @@ -78,9 +82,8 @@ } String path = PageLinks.toChange(changeResource.getProject(), changeResource.getChange().getId()); - if (commentIdx > -1) { - // path already contain a trailing /, hence we start from "commentIdx + 1" - path = path + uriPath.substring(commentIdx + 1); + if (finalSegment != null) { + path += finalSegment; } UrlModule.toGerrit(path, req, rsp); }
diff --git a/java/com/google/gerrit/httpd/UrlModule.java b/java/com/google/gerrit/httpd/UrlModule.java index 7a100c7..aedf8e9 100644 --- a/java/com/google/gerrit/httpd/UrlModule.java +++ b/java/com/google/gerrit/httpd/UrlModule.java
@@ -72,8 +72,7 @@ serveRegex("^/settings/?$").with(screen(PageLinks.SETTINGS)); serveRegex("^/register$").with(registerScreen(false)); serveRegex("^/register/(.+)$").with(registerScreen(true)); - serveRegex("^(?:/c)?/([1-9][0-9]*)/?$").with(NumericChangeIdRedirectServlet.class); - serveRegex("^(?:/c)?/([1-9][0-9]*)/comment/\\w+/?$").with(NumericChangeIdRedirectServlet.class); + serveRegex("^(?:/c)?/([1-9][0-9]*)/?.*$").with(NumericChangeIdRedirectServlet.class); serveRegex("^/p/(.*)$").with(queryProjectNew()); serveRegex("^/r/(.+)/?$").with(DirectChangeByCommit.class);
diff --git a/javatests/com/google/gerrit/acceptance/rest/RestApiServletIT.java b/javatests/com/google/gerrit/acceptance/rest/RestApiServletIT.java index 5c1f7c2..8011fb0 100644 --- a/javatests/com/google/gerrit/acceptance/rest/RestApiServletIT.java +++ b/javatests/com/google/gerrit/acceptance/rest/RestApiServletIT.java
@@ -33,6 +33,7 @@ import com.google.gerrit.extensions.restapi.Url; import com.google.gerrit.httpd.restapi.ParameterParser; import com.google.gerrit.httpd.restapi.RestApiServlet; +import com.google.gerrit.server.query.change.ChangeData; import com.google.inject.Inject; import java.io.IOException; import java.util.regex.Pattern; @@ -449,6 +450,19 @@ } @Test + public void testNumericChangeIdWithExtraSegments() throws Exception { + ChangeData changeData = createChange().getChange(); + int changeNumber = changeData.getId().get(); + + String finalSegment = "any/Thing"; + + String redirectUri = String.format("/c/%s/+/%d/%s", project.get(), changeNumber, finalSegment); + anonymousRestSession + .get(String.format("/c/%d/%s", changeNumber, finalSegment)) + .assertTemporaryRedirect(redirectUri); + } + + @Test public void testCommentLinkWithoutPrefixRedirects() throws Exception { int changeNumber = createChange().getChange().getId().get(); String commentId = "ff3303fd_8341647b";