Serve /robots.txt and /favicon.ico with StaticModule

As in If0a52a34, these used to come from the JettyServer
implementation, which is now gone.

Change-Id: I33d7ae030f917f929766ae2bac17bd1ce2ccd814
This commit is contained in:
Dave Borowitz 2015-12-14 11:48:28 -05:00
parent 10d85f593c
commit 4a68a0756f
5 changed files with 103 additions and 104 deletions

View File

@ -21,7 +21,6 @@ import com.google.gerrit.common.PageLinks;
import com.google.gerrit.httpd.raw.CatServlet;
import com.google.gerrit.httpd.raw.HostPageServlet;
import com.google.gerrit.httpd.raw.LegacyGerritServlet;
import com.google.gerrit.httpd.raw.RobotsServlet;
import com.google.gerrit.httpd.raw.SshInfoServlet;
import com.google.gerrit.httpd.raw.StaticModule;
import com.google.gerrit.httpd.raw.ToolServlet;
@ -105,8 +104,6 @@ class UrlModule extends ServletModule {
filter("/Documentation/").through(QueryDocumentationFilter.class);
serve("/robots.txt").with(RobotsServlet.class);
install(new StaticModule());
}

View File

@ -75,6 +75,7 @@ public abstract class ResourceServlet extends HttpServlet {
.put("gif", "image/gif")
.put("htm", "text/html")
.put("html", "text/html")
.put("ico", "image/x-icon")
.put("jpeg", "image/jpeg")
.put("jpg", "image/jpeg")
.put("js", JS)
@ -127,7 +128,12 @@ public abstract class ResourceServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse rsp)
throws IOException {
String name = CharMatcher.is('/').trimFrom(req.getPathInfo());
String name;
if (req.getPathInfo() == null) {
name = "/";
} else {
name = CharMatcher.is('/').trimFrom(req.getPathInfo());
}
if (isUnreasonableName(name)) {
notFound(rsp);
return;

View File

@ -1,97 +0,0 @@
// Copyright (C) 2013 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.raw;
import static java.nio.file.Files.exists;
import static java.nio.file.Files.isReadable;
import com.google.common.io.ByteStreams;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* This class provides a mechanism to use a configurable robots.txt file,
* outside of the .war of the application. In order to configure it add the
* following to the {@code httpd} section of the {@code gerrit.conf}
* file:
*
* <pre>
* [httpd]
* robotsFile = etc/myrobots.txt
* </pre>
*
* If the specified file name is relative it will resolved as a sub directory of
* the site directory, if it is absolute it will be used as is.
*
* If the specified file doesn't exist or isn't readable the servlet will
* default to the {@code robots.txt} file bundled with the .war file of the
* application.
*/
@SuppressWarnings("serial")
@Singleton
public class RobotsServlet extends HttpServlet {
private static final Logger log =
LoggerFactory.getLogger(RobotsServlet.class);
private final Path robotsFile;
@Inject
RobotsServlet(@GerritServerConfig final Config config, final SitePaths sitePaths) {
Path file = sitePaths.resolve(
config.getString("httpd", null, "robotsFile"));
if (file != null && (!exists(file) || !isReadable(file))) {
log.warn("Cannot read httpd.robotsFile, using default");
file = null;
}
robotsFile = file;
}
@Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp)
throws IOException {
rsp.setContentType("text/plain");
try (InputStream in = openRobotsFile();
OutputStream out = rsp.getOutputStream()) {
ByteStreams.copy(in, out);
}
}
private InputStream openRobotsFile() {
if (robotsFile != null) {
try {
return Files.newInputStream(robotsFile);
} catch (IOException e) {
log.warn("Cannot read " + robotsFile + "; using default", e);
}
}
return getServletContext().getResourceAsStream("/robots.txt");
}
}

View File

@ -0,0 +1,36 @@
// Copyright (C) 2015 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.raw;
import com.google.common.cache.Cache;
import java.nio.file.Path;
/** Serve a single static file, regardless of path. */
class SingleFileServlet extends ResourceServlet{
private static final long serialVersionUID = 1L;
private final Path path;
SingleFileServlet(Cache<Path, Resource> cache, Path path, boolean refresh) {
super(cache, refresh);
this.path = path;
}
@Override
protected Path getResourcePath(String pathInfo) {
return path;
}
}

View File

@ -14,10 +14,15 @@
package com.google.gerrit.httpd.raw;
import static java.nio.file.Files.exists;
import static java.nio.file.Files.isReadable;
import com.google.common.cache.Cache;
import com.google.gerrit.httpd.raw.ResourceServlet.Resource;
import com.google.gerrit.launcher.GerritLauncher;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Key;
import com.google.inject.Provides;
import com.google.inject.ProvisionException;
@ -26,6 +31,10 @@ import com.google.inject.name.Named;
import com.google.inject.name.Names;
import com.google.inject.servlet.ServletModule;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@ -37,8 +46,13 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class StaticModule extends ServletModule {
private static final String GWT_UI_SERVLET = "GwtUiServlet";
private static final Logger log =
LoggerFactory.getLogger(StaticModule.class);
private static final String DOC_SERVLET = "DocServlet";
private static final String FAVICON_SERVLET = "FaviconServlet";
private static final String GWT_UI_SERVLET = "GwtUiServlet";
private static final String ROBOTS_TXT_SERVLET = "RobotsTxtServlet";
static final String CACHE = "static_content";
@ -59,9 +73,10 @@ public class StaticModule extends ServletModule {
@Override
protected void configureServlets() {
serveRegex("^/Documentation/(.+)$").with(
Key.get(HttpServlet.class, Names.named(DOC_SERVLET)));
serveRegex("^/Documentation/(.+)$").with(named(DOC_SERVLET));
serve("/static/*").with(SiteStaticDirectoryServlet.class);
serve("/robots.txt").with(named(ROBOTS_TXT_SERVLET));
serve("/favicon.ico").with(named(FAVICON_SERVLET));
serveGwtUi();
install(new CacheModule() {
@Override
@ -112,6 +127,48 @@ public class StaticModule extends ServletModule {
}
}
@Provides
@Singleton
@Named(ROBOTS_TXT_SERVLET)
HttpServlet getRobotsTxtServlet(@GerritServerConfig Config cfg,
SitePaths sitePaths, @Named(CACHE) Cache<Path, Resource> cache) {
Path configPath = sitePaths.resolve(
cfg.getString("httpd", null, "robotsFile"));
if (configPath != null) {
if (exists(configPath) && isReadable(configPath)) {
return new SingleFileServlet(cache, configPath, true);
} else {
log.warn("Cannot read httpd.robotsFile, using default");
}
}
if (warFs != null) {
return new SingleFileServlet(cache, warFs.getPath("/robots.txt"), false);
} else {
return new SingleFileServlet(cache, webappSourcePath("robots.txt"), true);
}
}
@Provides
@Singleton
@Named(FAVICON_SERVLET)
HttpServlet getFaviconServlet(@Named(CACHE) Cache<Path, Resource> cache) {
if (warFs != null) {
return new SingleFileServlet(cache, warFs.getPath("/favicon.ico"), false);
} else {
return new SingleFileServlet(
cache, webappSourcePath("favicon.ico"), true);
}
}
private Path webappSourcePath(String name) {
return buckOut.resolveSibling("gerrit-war").resolve("src").resolve("main")
.resolve("webapp").resolve(name);
}
private static Key<HttpServlet> named(String name) {
return Key.get(HttpServlet.class, Names.named(name));
}
private static FileSystem getDistributionArchive() {
try {
return GerritLauncher.getDistributionArchiveFileSystem();