| // Copyright (C) 2009 The Android Open Source Project | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package com.google.gerrit.httpd; | |
| import static com.google.inject.Scopes.SINGLETON; | |
| import com.google.common.base.Strings; | |
| import com.google.gerrit.common.PageLinks; | |
| import com.google.gerrit.entities.Change; | |
| import com.google.gerrit.entities.Project; | |
| import com.google.gerrit.extensions.client.AuthType; | |
| import com.google.gerrit.httpd.RunAsFilter.RunAsFilterModule; | |
| import com.google.gerrit.httpd.raw.AuthorizationCheckServlet; | |
| import com.google.gerrit.httpd.raw.CatServlet; | |
| import com.google.gerrit.httpd.raw.SshInfoServlet; | |
| import com.google.gerrit.httpd.raw.ToolServlet; | |
| import com.google.gerrit.httpd.restapi.AccessRestApiServlet; | |
| import com.google.gerrit.httpd.restapi.AccountsRestApiServlet; | |
| import com.google.gerrit.httpd.restapi.ChangesRestApiServlet; | |
| import com.google.gerrit.httpd.restapi.ConfigRestApiServlet; | |
| import com.google.gerrit.httpd.restapi.GroupsRestApiServlet; | |
| import com.google.gerrit.httpd.restapi.ProjectsRestApiServlet; | |
| import com.google.gerrit.server.config.AuthConfig; | |
| import com.google.inject.Key; | |
| import com.google.inject.internal.UniqueAnnotations; | |
| import com.google.inject.servlet.ServletModule; | |
| import java.io.IOException; | |
| import javax.servlet.http.HttpServlet; | |
| import javax.servlet.http.HttpServletRequest; | |
| import javax.servlet.http.HttpServletResponse; | |
| import org.eclipse.jgit.lib.Constants; | |
| class UrlModule extends ServletModule { | |
| private AuthConfig authConfig; | |
| UrlModule(AuthConfig authConfig) { | |
| this.authConfig = authConfig; | |
| } | |
| @Override | |
| protected void configureServlets() { | |
| serve("/cat/*").with(CatServlet.class); | |
| if (authConfig.getAuthType() != AuthType.OAUTH && authConfig.getAuthType() != AuthType.OPENID) { | |
| serve("/logout").with(HttpLogoutServlet.class); | |
| serve("/signout").with(HttpLogoutServlet.class); | |
| } | |
| serve("/ssh_info").with(SshInfoServlet.class); | |
| serve("/Main.class").with(notFound()); | |
| serve("/com/google/gerrit/launcher/*").with(notFound()); | |
| serve("/servlet/*").with(notFound()); | |
| serve("/all").with(query("status:merged")); | |
| serve("/mine").with(screen(PageLinks.MINE)); | |
| serve("/open").with(query("status:open")); | |
| serve("/watched").with(query("is:watched status:open")); | |
| serve("/starred").with(query("is:starred")); | |
| serveRegex("^/settings/?$").with(screen(PageLinks.SETTINGS)); | |
| serveRegex("^/register$").with(registerScreen(false)); | |
| serveRegex("^/register/(.+)$").with(registerScreen(true)); | |
| serveRegex("^/([1-9][0-9]*)/?$").with(NumericChangeIdRedirectServlet.class); | |
| serveRegex("^/p/(.*)$").with(queryProjectNew()); | |
| serveRegex("^/r/(.+)/?$").with(DirectChangeByCommit.class); | |
| filter("/a/*").through(RequireIdentifiedUserFilter.class); | |
| // Must be after RequireIdentifiedUserFilter so auth happens before checking | |
| // for RunAs capability. | |
| install(new RunAsFilterModule()); | |
| serveRegex("^/(?:a/)?tools/(.*)$").with(ToolServlet.class); | |
| // Serve auth check. Mainly used by PolyGerrit for checking if a user is still logged in. | |
| serveRegex("^/(?:a/)?auth-check$").with(AuthorizationCheckServlet.class); | |
| // Bind servlets for REST root collections. | |
| // The '/plugins/' root collection is already handled by HttpPluginServlet | |
| // which is bound in HttpPluginModule. We cannot bind it here again although | |
| // this means that plugins can't add REST views on PLUGIN_KIND. | |
| serveRegex("^/(?:a/)?access/(.*)$").with(AccessRestApiServlet.class); | |
| serveRegex("^/(?:a/)?access$").with(AccessRestApiServlet.class); | |
| serveRegex("^/(?:a/)?accounts/(.*)$").with(AccountsRestApiServlet.class); | |
| serveRegex("^/(?:a/)?accounts$").with(AccountsRestApiServlet.class); | |
| serveRegex("^/(?:a/)?changes/(.*)$").with(ChangesRestApiServlet.class); | |
| serveRegex("^/(?:a/)?changes$").with(ChangesRestApiServlet.class); | |
| serveRegex("^/(?:a/)?config/(.*)$").with(ConfigRestApiServlet.class); | |
| serveRegex("^/(?:a/)?config$").with(ConfigRestApiServlet.class); | |
| serveRegex("^/(?:a/)?groups/(.*)?$").with(GroupsRestApiServlet.class); | |
| serveRegex("^/(?:a/)?groups$").with(GroupsRestApiServlet.class); | |
| serveRegex("^/(?:a/)?projects/(.*)?$").with(ProjectsRestApiServlet.class); | |
| serveRegex("^/(?:a/)?projects$").with(ProjectsRestApiServlet.class); | |
| serveRegex("^/Documentation$").with(redirectDocumentation()); | |
| serveRegex("^/Documentation/$").with(redirectDocumentation()); | |
| filter("/Documentation/*").through(QueryDocumentationFilter.class); | |
| } | |
| private Key<HttpServlet> notFound() { | |
| return key( | |
| new HttpServlet() { | |
| private static final long serialVersionUID = 1L; | |
| @Override | |
| protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException { | |
| rsp.sendError(HttpServletResponse.SC_NOT_FOUND); | |
| } | |
| }); | |
| } | |
| private Key<HttpServlet> screen(String target) { | |
| return key( | |
| new HttpServlet() { | |
| private static final long serialVersionUID = 1L; | |
| @Override | |
| protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException { | |
| toGerrit(target, req, rsp); | |
| } | |
| }); | |
| } | |
| private Key<HttpServlet> queryProjectNew() { | |
| return key( | |
| new HttpServlet() { | |
| private static final long serialVersionUID = 1L; | |
| @Override | |
| protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException { | |
| String name = req.getPathInfo(); | |
| if (Strings.isNullOrEmpty(name)) { | |
| toGerrit(PageLinks.ADMIN_PROJECTS, req, rsp); | |
| return; | |
| } | |
| while (name.endsWith("/")) { | |
| name = name.substring(0, name.length() - 1); | |
| } | |
| if (name.endsWith(Constants.DOT_GIT_EXT)) { | |
| name = | |
| name.substring( | |
| 0, // | |
| name.length() - Constants.DOT_GIT_EXT.length()); | |
| } | |
| while (name.endsWith("/")) { | |
| name = name.substring(0, name.length() - 1); | |
| } | |
| Project.NameKey project = Project.nameKey(name); | |
| toGerrit( | |
| PageLinks.toChangeQuery(PageLinks.projectQuery(project, Change.Status.NEW)), | |
| req, | |
| rsp); | |
| } | |
| }); | |
| } | |
| private Key<HttpServlet> query(String query) { | |
| return key( | |
| new HttpServlet() { | |
| private static final long serialVersionUID = 1L; | |
| @Override | |
| protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException { | |
| toGerrit(PageLinks.toChangeQuery(query), req, rsp); | |
| } | |
| }); | |
| } | |
| private Key<HttpServlet> key(HttpServlet servlet) { | |
| final Key<HttpServlet> srv = Key.get(HttpServlet.class, UniqueAnnotations.create()); | |
| bind(srv).toProvider(() -> servlet).in(SINGLETON); | |
| return srv; | |
| } | |
| private Key<HttpServlet> registerScreen(final Boolean slash) { | |
| return key( | |
| new HttpServlet() { | |
| private static final long serialVersionUID = 1L; | |
| @Override | |
| protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException { | |
| String path = String.format("/register%s", slash ? req.getPathInfo() : ""); | |
| toGerrit(path, req, rsp); | |
| } | |
| }); | |
| } | |
| private Key<HttpServlet> redirectDocumentation() { | |
| return key( | |
| new HttpServlet() { | |
| private static final long serialVersionUID = 1L; | |
| @Override | |
| protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException { | |
| String path = "/Documentation/index.html"; | |
| toGerrit(path, req, rsp); | |
| } | |
| }); | |
| } | |
| static void toGerrit(String target, HttpServletRequest req, HttpServletResponse rsp) | |
| throws IOException { | |
| final StringBuilder url = new StringBuilder(); | |
| url.append(req.getContextPath()); | |
| url.append(target); | |
| rsp.sendRedirect(url.toString()); | |
| } | |
| } |