Skip to content

Commit 99dd82f

Browse files
Only set LEGACY UriCompliance for EE8 runtime by default
Signed-off-by: Lachlan Roberts <lachlan.p.roberts@gmail.com>
1 parent f079dea commit 99dd82f

File tree

12 files changed

+84
-45
lines changed

12 files changed

+84
-45
lines changed

runtime/impl/src/main/java/com/google/apphosting/runtime/AppEngineConstants.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@
2020

2121
/** {@code AppEngineConstants} centralizes some constants that are specific to our use of Jetty. */
2222
public final class AppEngineConstants {
23+
24+
/**
25+
* If Legacy Mode is turned on, then Jetty is configured to be more forgiving of bad requests and
26+
* to act more in the style of Jetty-9.3
27+
*/
28+
public static final boolean LEGACY_MODE =
29+
Boolean.getBoolean("com.google.apphosting.runtime.jetty94.LEGACY_MODE");
30+
31+
public static final String GAE_RUNTIME = System.getenv("GAE_RUNTIME");
32+
2333
/**
2434
* This {@code ServletContext} attribute contains the {@link AppVersion} for the current
2535
* application.

runtime/impl/src/main/java/com/google/apphosting/runtime/RequestRunner.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.google.apphosting.runtime;
1818

19+
import static com.google.apphosting.runtime.AppEngineConstants.GAE_RUNTIME;
1920
import static java.util.concurrent.TimeUnit.MILLISECONDS;
2021

2122
import com.google.appengine.api.ThreadManager;
@@ -240,7 +241,7 @@ private void dispatchBackgroundRequest() throws InterruptedException, TimeoutExc
240241
String requestId = getBackgroundRequestId(upRequest);
241242
// For java21 runtime, RPC path, do the new background thread handling for now, and keep it for
242243
// other runtimes.
243-
if (!Objects.equals(System.getenv("GAE_RUNTIME"), "java21")) {
244+
if (!Objects.equals(GAE_RUNTIME, "java21")) {
244245
// Wait here for synchronization with the ThreadFactory.
245246
CountDownLatch latch = ThreadGroupPool.resetCurrentThread();
246247
Thread thread = new ThreadProxy();

runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/AppVersionHandlerFactory.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,28 @@
2222
import org.eclipse.jetty.server.Server;
2323

2424
public interface AppVersionHandlerFactory {
25+
26+
enum EEVersion
27+
{
28+
EE8,
29+
EE10
30+
}
31+
32+
static EEVersion getEEVersion() {
33+
if (Boolean.getBoolean("appengine.use.EE10"))
34+
return EEVersion.EE10;
35+
else
36+
return EEVersion.EE8;
37+
}
38+
2539
static AppVersionHandlerFactory newInstance(Server server, String serverInfo) {
26-
if (Boolean.getBoolean("appengine.use.EE10")) {
27-
return new EE10AppVersionHandlerFactory(server, serverInfo);
28-
} else {
29-
return new EE8AppVersionHandlerFactory(server, serverInfo);
40+
switch (getEEVersion()) {
41+
case EE10:
42+
return new EE10AppVersionHandlerFactory(server, serverInfo);
43+
case EE8:
44+
return new EE8AppVersionHandlerFactory(server, serverInfo);
45+
default:
46+
throw new IllegalStateException("Unknown EE version: " + getEEVersion());
3047
}
3148
}
3249

runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
*/
1616
package com.google.apphosting.runtime.jetty;
1717

18+
import static com.google.apphosting.runtime.AppEngineConstants.GAE_RUNTIME;
1819
import static com.google.apphosting.runtime.AppEngineConstants.HTTP_CONNECTOR_MODE;
1920
import static com.google.apphosting.runtime.AppEngineConstants.IGNORE_RESPONSE_SIZE_LIMIT;
21+
import static com.google.apphosting.runtime.AppEngineConstants.LEGACY_MODE;
2022
import static java.nio.charset.StandardCharsets.UTF_8;
2123

2224
import com.google.apphosting.api.ApiProxy;
@@ -50,7 +52,7 @@
5052
import org.eclipse.jetty.http.UriCompliance;
5153
import org.eclipse.jetty.server.HttpConfiguration;
5254
import org.eclipse.jetty.server.Server;
53-
import org.eclipse.jetty.server.SizeLimitHandler;
55+
import org.eclipse.jetty.server.handler.SizeLimitHandler;
5456
import org.eclipse.jetty.util.VirtualThreads;
5557
import org.eclipse.jetty.util.thread.QueuedThreadPool;
5658

@@ -64,13 +66,6 @@ public class JettyServletEngineAdapter implements ServletEngineAdapter {
6466
private static final int MAX_THREAD_POOL_THREADS = 100;
6567
private static final long MAX_RESPONSE_SIZE = 32 * 1024 * 1024;
6668

67-
/**
68-
* If Legacy Mode is turned on, then Jetty is configured to be more forgiving of bad requests and
69-
* to act more in the style of Jetty-9.3
70-
*/
71-
public static final boolean LEGACY_MODE =
72-
Boolean.getBoolean("com.google.apphosting.runtime.jetty94.LEGACY_MODE");
73-
7469
private AppVersionKey lastAppVersionKey;
7570

7671
static {
@@ -107,7 +102,7 @@ public void start(String serverInfo, ServletEngineAdapter.Config runtimeOptions)
107102
new QueuedThreadPool(MAX_THREAD_POOL_THREADS, MIN_THREAD_POOL_THREADS);
108103
// Try to enable virtual threads if requested and on java21:
109104
if (Boolean.getBoolean("appengine.use.virtualthreads")
110-
&& "java21".equals(System.getenv("GAE_RUNTIME"))) {
105+
&& "java21".equals(GAE_RUNTIME)) {
111106
threadPool.setVirtualThreadsExecutor(VirtualThreads.getDefaultVirtualThreadsExecutor());
112107
logger.atInfo().log("Configuring Appengine web server virtual threads.");
113108
}
@@ -137,8 +132,14 @@ public void run(Runnable runnable) {
137132
httpConfiguration.setSendDateHeader(false);
138133
httpConfiguration.setSendServerVersion(false);
139134
httpConfiguration.setSendXPoweredBy(false);
140-
httpConfiguration.setUriCompliance(UriCompliance.LEGACY);
135+
136+
// If runtime is using EE8, then set URI compliance to LEGACY to behave like Jetty 9.4.
137+
if (Objects.equals(AppVersionHandlerFactory.getEEVersion(), AppVersionHandlerFactory.EEVersion.EE8)) {
138+
httpConfiguration.setUriCompliance(UriCompliance.LEGACY);
139+
}
140+
141141
if (LEGACY_MODE) {
142+
httpConfiguration.setUriCompliance(UriCompliance.LEGACY);
142143
httpConfiguration.setHttpCompliance(HttpCompliance.RFC7230_LEGACY);
143144
httpConfiguration.setRequestCookieCompliance(CookieCompliance.RFC2965);
144145
httpConfiguration.setResponseCookieCompliance(CookieCompliance.RFC2965);

runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/delegate/impl/DelegateRpcExchange.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,32 @@
1616

1717
package com.google.apphosting.runtime.jetty.delegate.impl;
1818

19+
import static com.google.apphosting.runtime.AppEngineConstants.LEGACY_MODE;
20+
1921
import com.google.apphosting.base.protos.HttpPb;
2022
import com.google.apphosting.base.protos.HttpPb.ParsedHttpHeader;
2123
import com.google.apphosting.base.protos.RuntimePb;
2224
import com.google.apphosting.runtime.MutableUpResponse;
2325
import com.google.apphosting.runtime.jetty.delegate.api.DelegateExchange;
2426
import com.google.common.base.Ascii;
2527
import com.google.protobuf.ByteString;
26-
import org.eclipse.jetty.http.HttpFields;
27-
import org.eclipse.jetty.http.HttpMethod;
28-
import org.eclipse.jetty.io.ByteBufferAccumulator;
29-
import org.eclipse.jetty.io.Content;
30-
import org.eclipse.jetty.util.Attributes;
31-
import org.eclipse.jetty.util.Callback;
32-
3328
import java.net.InetSocketAddress;
3429
import java.nio.ByteBuffer;
3530
import java.util.Set;
3631
import java.util.concurrent.CompletableFuture;
3732
import java.util.concurrent.ExecutionException;
3833
import java.util.concurrent.atomic.AtomicReference;
34+
import org.eclipse.jetty.http.HttpFields;
35+
import org.eclipse.jetty.http.HttpMethod;
36+
import org.eclipse.jetty.io.ByteBufferAccumulator;
37+
import org.eclipse.jetty.io.Content;
38+
import org.eclipse.jetty.util.Attributes;
39+
import org.eclipse.jetty.util.Callback;
3940

4041
public class DelegateRpcExchange implements DelegateExchange {
4142
private static final Content.Chunk EOF = Content.Chunk.EOF;
4243
private static final String X_GOOGLE_INTERNAL_SKIPADMINCHECK = "x-google-internal-skipadmincheck";
4344
private static final String SKIP_ADMIN_CHECK_ATTR = "com.google.apphosting.internal.SkipAdminCheck";
44-
static final boolean LEGACY_MODE =
45-
Boolean.getBoolean("com.google.apphosting.runtime.jetty94.LEGACY_MODE");
4645

4746
private final HttpPb.HttpRequest _request;
4847
private final AtomicReference<Content.Chunk> _content = new AtomicReference<>();

runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/AppEngineWebAppContext.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import com.google.apphosting.api.ApiProxy;
2323
import com.google.apphosting.api.ApiProxy.LogRecord;
24+
import com.google.apphosting.runtime.AppEngineConstants;
2425
import com.google.apphosting.runtime.jetty.EE10AppEngineAuthentication;
2526
import com.google.apphosting.utils.servlet.ee10.DeferredTaskServlet;
2627
import com.google.apphosting.utils.servlet.ee10.JdbcMySqlConnectionCleanupFilter;
@@ -278,6 +279,9 @@ public boolean handle(Request request, Response response, Callback callback) thr
278279
protected ServletHandler newServletHandler() {
279280
ServletHandler handler = new ServletHandler();
280281
handler.setAllowDuplicateMappings(true);
282+
if (AppEngineConstants.LEGACY_MODE) {
283+
handler.setDecodeAmbiguousURIs(true);
284+
}
281285
return handler;
282286
}
283287

runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/JettyHttpProxy.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,19 @@
2020
import com.google.apphosting.base.protos.RuntimePb;
2121
import com.google.apphosting.base.protos.RuntimePb.UPRequest;
2222
import com.google.apphosting.base.protos.RuntimePb.UPResponse;
23+
import com.google.apphosting.runtime.AppEngineConstants;
2324
import com.google.apphosting.runtime.LocalRpcContext;
2425
import com.google.apphosting.runtime.ServletEngineAdapter;
2526
import com.google.apphosting.runtime.anyrpc.EvaluationRuntimeServerInterface;
2627
import com.google.apphosting.runtime.jetty.AppInfoFactory;
27-
import com.google.apphosting.runtime.jetty.JettyServletEngineAdapter;
28+
import com.google.apphosting.runtime.jetty.AppVersionHandlerFactory;
2829
import com.google.common.base.Ascii;
2930
import com.google.common.base.Throwables;
3031
import com.google.common.flogger.GoogleLogger;
3132
import com.google.common.primitives.Ints;
3233
import java.time.Duration;
3334
import java.util.Map;
35+
import java.util.Objects;
3436
import java.util.concurrent.ExecutionException;
3537
import java.util.logging.Level;
3638
import org.eclipse.jetty.http.CookieCompliance;
@@ -94,8 +96,14 @@ public static ServerConnector newConnector(
9496

9597
HttpConfiguration config =
9698
connector.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration();
97-
config.setUriCompliance(UriCompliance.LEGACY);
98-
if (JettyServletEngineAdapter.LEGACY_MODE) {
99+
100+
// If runtime is using EE8, then set URI compliance to LEGACY to behave like Jetty 9.4.
101+
if (Objects.equals(AppVersionHandlerFactory.getEEVersion(), AppVersionHandlerFactory.EEVersion.EE8)) {
102+
config.setUriCompliance(UriCompliance.LEGACY);
103+
}
104+
105+
if (AppEngineConstants.LEGACY_MODE) {
106+
config.setUriCompliance(UriCompliance.LEGACY);
99107
config.setHttpCompliance(HttpCompliance.RFC7230_LEGACY);
100108
config.setRequestCookieCompliance(CookieCompliance.RFC2965);
101109
config.setResponseCookieCompliance(CookieCompliance.RFC2965);

runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppEngineWebAppContext.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.google.apphosting.runtime.jetty9;
1818

19+
import static com.google.apphosting.runtime.AppEngineConstants.GAE_RUNTIME;
1920
import static com.google.common.base.StandardSystemProperty.JAVA_IO_TMPDIR;
2021
import static java.nio.charset.StandardCharsets.UTF_8;
2122

@@ -79,8 +80,7 @@ public class AppEngineWebAppContext extends WebAppContext {
7980
private static final int MAX_RESPONSE_SIZE = 32 * 1024 * 1024;
8081
private static final boolean APP_IS_ASYNC =
8182
Boolean.getBoolean(RpcConnection.ASYNC_ENABLE_PPROPERTY);
82-
private static final boolean IS_JAVA_8_RUNTIME =
83-
Objects.equals(System.getenv("GAE_RUNTIME"), "java8");
83+
private static final boolean IS_JAVA_8_RUNTIME = Objects.equals(GAE_RUNTIME, "java8");
8484
private static final ImmutableSet<HolderMatcher> EMPTY_SET =
8585
ImmutableSet.<HolderMatcher>builder().build();
8686

runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpProxy.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package com.google.apphosting.runtime.jetty9;
1818

19+
import static com.google.apphosting.runtime.AppEngineConstants.LEGACY_MODE;
20+
1921
import com.google.apphosting.base.protos.AppLogsPb;
2022
import com.google.apphosting.base.protos.RuntimePb;
2123
import com.google.apphosting.base.protos.RuntimePb.UPRequest;
@@ -93,7 +95,7 @@ public static ServerConnector newConnector(
9395

9496
HttpConnectionFactory factory = connector.getConnectionFactory(HttpConnectionFactory.class);
9597
factory.setHttpCompliance(
96-
RpcConnector.LEGACY_MODE ? HttpCompliance.RFC7230_LEGACY : HttpCompliance.RFC7230);
98+
LEGACY_MODE ? HttpCompliance.RFC7230_LEGACY : HttpCompliance.RFC7230);
9799

98100
HttpConfiguration config = factory.getHttpConfiguration();
99101
config.setRequestHeaderSize(runtimeOptions.jettyRequestHeaderSize());

runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyServletEngineAdapter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.google.apphosting.runtime.jetty9;
1818

19+
import static com.google.apphosting.runtime.AppEngineConstants.GAE_RUNTIME;
1920
import static com.google.apphosting.runtime.AppEngineConstants.HTTP_CONNECTOR_MODE;
2021
import static com.google.apphosting.runtime.AppEngineConstants.IGNORE_RESPONSE_SIZE_LIMIT;
2122
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -63,7 +64,7 @@ public class JettyServletEngineAdapter implements ServletEngineAdapter {
6364
// java.util.logging) instead of writing to System.err
6465
// Documentation: http://www.eclipse.org/jetty/documentation/current/configuring-logging.html
6566
System.setProperty("org.eclipse.jetty.util.log.class", JettyLogger.class.getName());
66-
if (Objects.equals(System.getenv("GAE_RUNTIME"), "java8")) {
67+
if (Objects.equals(GAE_RUNTIME, "java8")) {
6768
// Remove internal URLs.
6869
System.setProperty("java.vendor.url", "");
6970
System.setProperty("java.vendor.url.bug", "");
@@ -118,7 +119,7 @@ public void start(String serverInfo, ServletEngineAdapter.Config runtimeOptions)
118119
server.setHandler(appVersionHandlerMap);
119120

120121
boolean ignoreResponseSizeLimit =
121-
Objects.equals(System.getenv("GAE_RUNTIME"), "java8")
122+
Objects.equals(GAE_RUNTIME, "java8")
122123
|| Boolean.getBoolean(IGNORE_RESPONSE_SIZE_LIMIT);
123124
if (!ignoreResponseSizeLimit && !isHttpConnectorMode) {
124125
server.insertHandler(new SizeLimitHandler(-1, MAX_RESPONSE_SIZE));

0 commit comments

Comments
 (0)