Skip to content

Commit

Permalink
Merge pull request #105 from GoogleCloudPlatform:defaultServlet-class…
Browse files Browse the repository at this point in the history
…loading

PiperOrigin-RevId: 627582402
Change-Id: Ib2ff3d4d9af285738adf92ffe3bc90014338982f
  • Loading branch information
gae-java-bot committed Apr 24, 2024
2 parents b57b34a + b8ac101 commit 97f644a
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.VirtualThreads;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;

import java.io.File;
Expand Down Expand Up @@ -104,12 +106,21 @@ public void start(String serverInfo, ServletEngineAdapter.Config runtimeOptions)
threadPool.setVirtualThreadsExecutor(VirtualThreads.getDefaultVirtualThreadsExecutor());
logger.atInfo().log("Configuring Appengine web server virtual threads.");
}

// The server.getDefaultStyleSheet() returns is returning null because of some classloading issue,
// so we get the StyleSheet here to ensure it returns the correct value.
Resource styleSheet = ResourceFactory.root().newResource(getClass().getClassLoader().getResource("jetty-dir.css"));
server =
new Server(threadPool) {
@Override
public InvocationType getInvocationType() {
return InvocationType.BLOCKING;
}

@Override
public Resource getDefaultStyleSheet() {
return styleSheet;
}
};

rpcConnector = new DelegateConnector(server, "RPC") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@

package com.google.apphosting.runtime.jetty.ee10;

import static com.google.common.base.StandardSystemProperty.JAVA_IO_TMPDIR;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.apphosting.api.ApiProxy;
import com.google.apphosting.api.ApiProxy.LogRecord;
import com.google.apphosting.runtime.jetty.EE10AppEngineAuthentication;
Expand All @@ -31,21 +28,6 @@
import jakarta.servlet.DispatcherType;
import jakarta.servlet.Filter;
import jakarta.servlet.Servlet;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.EventListener;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.jetty.ee10.servlet.FilterHolder;
import org.eclipse.jetty.ee10.servlet.FilterMapping;
import org.eclipse.jetty.ee10.servlet.Holder;
Expand All @@ -63,6 +45,25 @@
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceFactory;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.EventListener;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;

import static com.google.common.base.StandardSystemProperty.JAVA_IO_TMPDIR;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
* {@code AppEngineWebAppContext} is a customization of Jetty's {@link WebAppContext} that is aware
* of the {@link ApiProxy} and can provide custom logging and authentication.
Expand Down Expand Up @@ -235,52 +236,59 @@ public void doStart() throws Exception {

@Override
protected void startContext() throws Exception {
// startWebapp is called after the web.xml metadata has been resolved, so we can
// clean configuration here:
// - Removed deprecated filters and servlets
// - Ensure known runtime filters/servlets are instantiated from this classloader
// - Ensure known runtime mappings exist.
ServletHandler servletHandler = getServletHandler();
TrimmedFilters trimmedFilters =
new TrimmedFilters(
servletHandler.getFilters(),
servletHandler.getFilterMappings(),
DEPRECATED_SERVLETS_FILTERS);
trimmedFilters.ensure(
"CloudSqlConnectionCleanupFilter", JdbcMySqlConnectionCleanupFilter.class, "/*");

TrimmedServlets trimmedServlets =
new TrimmedServlets(
servletHandler.getServlets(),
servletHandler.getServletMappings(),
DEPRECATED_SERVLETS_FILTERS);
trimmedServlets.ensure("_ah_warmup", WarmupServlet.class, "/_ah/warmup");
trimmedServlets.ensure(
"_ah_sessioncleanup", SessionCleanupServlet.class, "/_ah/sessioncleanup");
trimmedServlets.ensure(
"_ah_queue_deferred", DeferredTaskServlet.class, "/_ah/queue/__deferred__");
trimmedServlets.ensure("_ah_snapshot", SnapshotServlet.class, "/_ah/snapshot");
trimmedServlets.ensure("_ah_default", ResourceFileServlet.class, "/");
trimmedServlets.ensure("default", NamedDefaultServlet.class);
trimmedServlets.ensure("jsp", NamedJspServlet.class);

trimmedServlets.instantiateJettyServlets();
trimmedFilters.instantiateJettyFilters();
instantiateJettyListeners();

servletHandler.setFilters(trimmedFilters.getHolders());
servletHandler.setFilterMappings(trimmedFilters.getMappings());
servletHandler.setServlets(trimmedServlets.getHolders());
servletHandler.setServletMappings(trimmedServlets.getMappings());
servletHandler.setAllowDuplicateMappings(true);

// Protect deferred task queue with constraint
ConstraintSecurityHandler security = (ConstraintSecurityHandler) getSecurityHandler();
ConstraintMapping cm = new ConstraintMapping();
cm.setConstraint(
Constraint.from("deferred_queue", Constraint.Authorization.SPECIFIC_ROLE, "admin"));
cm.setPathSpec("/_ah/queue/__deferred__");
security.addConstraintMapping(cm);
ServletHandler servletHandler = getServletHandler();
getServletHandler().addListener(new ListenerHolder() {
@Override
public void doStart() throws Exception {
// This Listener doStart is called after the web.xml metadata has been resolved, so we can
// clean configuration here:
// - Removed deprecated filters and servlets
// - Ensure known runtime filters/servlets are instantiated from this classloader
// - Ensure known runtime mappings exist.
setListener(new EventListener() {});

TrimmedFilters trimmedFilters =
new TrimmedFilters(
servletHandler.getFilters(),
servletHandler.getFilterMappings(),
DEPRECATED_SERVLETS_FILTERS);
trimmedFilters.ensure(
"CloudSqlConnectionCleanupFilter", JdbcMySqlConnectionCleanupFilter.class, "/*");

TrimmedServlets trimmedServlets =
new TrimmedServlets(
servletHandler.getServlets(),
servletHandler.getServletMappings(),
DEPRECATED_SERVLETS_FILTERS);
trimmedServlets.ensure("_ah_warmup", WarmupServlet.class, "/_ah/warmup");
trimmedServlets.ensure(
"_ah_sessioncleanup", SessionCleanupServlet.class, "/_ah/sessioncleanup");
trimmedServlets.ensure(
"_ah_queue_deferred", DeferredTaskServlet.class, "/_ah/queue/__deferred__");
trimmedServlets.ensure("_ah_snapshot", SnapshotServlet.class, "/_ah/snapshot");
trimmedServlets.ensure("_ah_default", ResourceFileServlet.class, "/");
trimmedServlets.ensure("default", NamedDefaultServlet.class);
trimmedServlets.ensure("jsp", NamedJspServlet.class);

trimmedServlets.instantiateJettyServlets();
trimmedFilters.instantiateJettyFilters();
instantiateJettyListeners();

servletHandler.setFilters(trimmedFilters.getHolders());
servletHandler.setFilterMappings(trimmedFilters.getMappings());
servletHandler.setServlets(trimmedServlets.getHolders());
servletHandler.setServletMappings(trimmedServlets.getMappings());
servletHandler.setAllowDuplicateMappings(true);

// Protect deferred task queue with constraint
ConstraintSecurityHandler security = (ConstraintSecurityHandler) getSecurityHandler();
ConstraintMapping cm = new ConstraintMapping();
cm.setConstraint(
Constraint.from("deferred_queue", Constraint.Authorization.SPECIFIC_ROLE, "admin"));
cm.setPathSpec("/_ah/queue/__deferred__");
security.addConstraintMapping(cm);
}
});

// continue starting the webapp
super.startContext();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@

package com.google.apphosting.runtime.jetty.ee8;

import static com.google.common.base.StandardSystemProperty.JAVA_IO_TMPDIR;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.apphosting.api.ApiProxy;
import com.google.apphosting.api.ApiProxy.LogRecord;
import com.google.apphosting.runtime.jetty.AppEngineAuthentication;
Expand All @@ -28,6 +25,25 @@
import com.google.apphosting.utils.servlet.SnapshotServlet;
import com.google.apphosting.utils.servlet.WarmupServlet;
import com.google.common.collect.ImmutableSet;
import org.eclipse.jetty.ee8.nested.ServletConstraint;
import org.eclipse.jetty.ee8.security.ConstraintMapping;
import org.eclipse.jetty.ee8.security.ConstraintSecurityHandler;
import org.eclipse.jetty.ee8.servlet.FilterHolder;
import org.eclipse.jetty.ee8.servlet.FilterMapping;
import org.eclipse.jetty.ee8.servlet.Holder;
import org.eclipse.jetty.ee8.servlet.ListenerHolder;
import org.eclipse.jetty.ee8.servlet.ServletHandler;
import org.eclipse.jetty.ee8.servlet.ServletHolder;
import org.eclipse.jetty.ee8.servlet.ServletMapping;
import org.eclipse.jetty.ee8.webapp.WebAppContext;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceFactory;

import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
Expand All @@ -43,24 +59,9 @@
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.ee8.nested.ServletConstraint;
import org.eclipse.jetty.ee8.security.ConstraintMapping;
import org.eclipse.jetty.ee8.security.ConstraintSecurityHandler;
import org.eclipse.jetty.ee8.servlet.FilterHolder;
import org.eclipse.jetty.ee8.servlet.FilterMapping;
import org.eclipse.jetty.ee8.servlet.Holder;
import org.eclipse.jetty.ee8.servlet.ListenerHolder;
import org.eclipse.jetty.ee8.servlet.ServletHandler;
import org.eclipse.jetty.ee8.servlet.ServletHolder;
import org.eclipse.jetty.ee8.servlet.ServletMapping;
import org.eclipse.jetty.ee8.webapp.WebAppContext;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceFactory;

import static com.google.common.base.StandardSystemProperty.JAVA_IO_TMPDIR;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
* {@code AppEngineWebAppContext} is a customization of Jetty's {@link WebAppContext} that is aware
Expand Down Expand Up @@ -239,53 +240,61 @@ public void doStart() throws Exception {

@Override
protected void startContext() throws Exception {
// startWebapp is called after the web.xml metadata has been resolved, so we can
// clean configuration here:
// - Removed deprecated filters and servlets
// - Ensure known runtime filters/servlets are instantiated from this classloader
// - Ensure known runtime mappings exist.
ServletHandler servletHandler = getServletHandler();
TrimmedFilters trimmedFilters =
new TrimmedFilters(
servletHandler.getFilters(),
servletHandler.getFilterMappings(),
DEPRECATED_SERVLETS_FILTERS);
trimmedFilters.ensure(
"CloudSqlConnectionCleanupFilter", JdbcMySqlConnectionCleanupFilter.class, "/*");

TrimmedServlets trimmedServlets =
new TrimmedServlets(
servletHandler.getServlets(),
servletHandler.getServletMappings(),
DEPRECATED_SERVLETS_FILTERS);
trimmedServlets.ensure("_ah_warmup", WarmupServlet.class, "/_ah/warmup");
trimmedServlets.ensure(
"_ah_sessioncleanup", SessionCleanupServlet.class, "/_ah/sessioncleanup");
trimmedServlets.ensure(
"_ah_queue_deferred", DeferredTaskServlet.class, "/_ah/queue/__deferred__");
trimmedServlets.ensure("_ah_snapshot", SnapshotServlet.class, "/_ah/snapshot");
trimmedServlets.ensure("_ah_default", ResourceFileServlet.class, "/");
trimmedServlets.ensure("default", NamedDefaultServlet.class);
trimmedServlets.ensure("jsp", NamedJspServlet.class);

trimmedServlets.instantiateJettyServlets();
trimmedFilters.instantiateJettyFilters();
instantiateJettyListeners();

servletHandler.setFilters(trimmedFilters.getHolders());
servletHandler.setFilterMappings(trimmedFilters.getMappings());
servletHandler.setServlets(trimmedServlets.getHolders());
servletHandler.setServletMappings(trimmedServlets.getMappings());
servletHandler.setAllowDuplicateMappings(true);

// Protect deferred task queue with constraint
ConstraintSecurityHandler security = getChildHandlerByClass(ConstraintSecurityHandler.class);
ConstraintMapping cm = new ConstraintMapping();
cm.setConstraint(new ServletConstraint("deferred_queue", "admin"));
cm.setPathSpec("/_ah/queue/__deferred__");
security.addConstraintMapping(cm);

// continue starting the webapp
getServletHandler().addListener(new ListenerHolder() {
@Override
public void doStart() throws Exception {

// This Listener doStart is called after the web.xml metadata has been resolved, so we can
// clean configuration here:
// - Removed deprecated filters and servlets
// - Ensure known runtime filters/servlets are instantiated from this classloader
// - Ensure known runtime mappings exist.
setListener(new EventListener() {});

TrimmedFilters trimmedFilters =
new TrimmedFilters(
servletHandler.getFilters(),
servletHandler.getFilterMappings(),
DEPRECATED_SERVLETS_FILTERS);
trimmedFilters.ensure(
"CloudSqlConnectionCleanupFilter", JdbcMySqlConnectionCleanupFilter.class, "/*");

TrimmedServlets trimmedServlets =
new TrimmedServlets(
servletHandler.getServlets(),
servletHandler.getServletMappings(),
DEPRECATED_SERVLETS_FILTERS);
trimmedServlets.ensure("_ah_warmup", WarmupServlet.class, "/_ah/warmup");
trimmedServlets.ensure(
"_ah_sessioncleanup", SessionCleanupServlet.class, "/_ah/sessioncleanup");
trimmedServlets.ensure(
"_ah_queue_deferred", DeferredTaskServlet.class, "/_ah/queue/__deferred__");
trimmedServlets.ensure("_ah_snapshot", SnapshotServlet.class, "/_ah/snapshot");
trimmedServlets.ensure("_ah_default", ResourceFileServlet.class, "/");
trimmedServlets.ensure("default", NamedDefaultServlet.class);
trimmedServlets.ensure("jsp", NamedJspServlet.class);

trimmedServlets.instantiateJettyServlets();
trimmedFilters.instantiateJettyFilters();
instantiateJettyListeners();

servletHandler.setFilters(trimmedFilters.getHolders());
servletHandler.setFilterMappings(trimmedFilters.getMappings());
servletHandler.setServlets(trimmedServlets.getHolders());
servletHandler.setServletMappings(trimmedServlets.getMappings());
servletHandler.setAllowDuplicateMappings(true);

// Protect deferred task queue with constraint
ConstraintSecurityHandler security = getChildHandlerByClass(ConstraintSecurityHandler.class);
ConstraintMapping cm = new ConstraintMapping();
cm.setConstraint(new ServletConstraint("deferred_queue", "admin"));
cm.setPathSpec("/_ah/queue/__deferred__");
security.addConstraintMapping(cm);
}
});

// continue starting the webapp
super.startContext();
}

Expand Down

0 comments on commit 97f644a

Please sign in to comment.