From 23847fc8c572f779f4a75cac868f0f2ec7e5b837 Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Thu, 6 Jun 2024 12:47:49 -0700 Subject: [PATCH 01/28] Upgrade GAE Java version from 2.0.27 to 2.0.28 and prepare next version 2.0.29-SNAPSHOT PiperOrigin-RevId: 640989663 Change-Id: Iccf3448b316f18617cbf1b7d613f2a7e65a9c1f6 --- README.md | 14 +++++++------- TRYLATESTBITSINPROD.md | 4 ++-- api/pom.xml | 4 ++-- api_dev/pom.xml | 2 +- api_legacy/pom.xml | 2 +- appengine-api-1.0-sdk/pom.xml | 2 +- appengine-api-stubs/pom.xml | 2 +- appengine_init/pom.xml | 2 +- appengine_jsr107/pom.xml | 2 +- appengine_resources/pom.xml | 2 +- appengine_setup/apiserver_local/pom.xml | 2 +- appengine_setup/pom.xml | 2 +- appengine_setup/test/pom.xml | 2 +- .../appengine/setup/test/Jetty12TestAppTest.java | 2 +- .../setup/test/SpringBootTestAppTest.java | 2 +- .../google/appengine/setup/test/util/TestUtil.java | 2 +- appengine_setup/testapps/jetty12_testapp/pom.xml | 6 +++--- appengine_setup/testapps/pom.xml | 2 +- .../testapps/springboot_testapp/pom.xml | 6 +++--- appengine_setup/testapps/testapps_common/pom.xml | 2 +- appengine_testing/pom.xml | 2 +- appengine_testing_tests/pom.xml | 2 +- applications/pom.xml | 2 +- applications/proberapp/pom.xml | 2 +- applications/springboot/pom.xml | 2 +- e2etests/devappservertests/pom.xml | 2 +- e2etests/pom.xml | 2 +- e2etests/stagingtests/pom.xml | 2 +- e2etests/testlocalapps/allinone/pom.xml | 2 +- e2etests/testlocalapps/allinone_jakarta/pom.xml | 2 +- e2etests/testlocalapps/badcron/pom.xml | 2 +- e2etests/testlocalapps/bundle_standard/pom.xml | 2 +- .../pom.xml | 2 +- .../bundle_standard_with_no_jsp/pom.xml | 2 +- .../pom.xml | 2 +- .../testlocalapps/cron-bad-job-age-limit/pom.xml | 2 +- .../cron-good-retry-parameters/pom.xml | 2 +- .../cron-negative-max-backoff/pom.xml | 2 +- .../cron-negative-retry-limit/pom.xml | 2 +- .../testlocalapps/cron-two-max-doublings/pom.xml | 2 +- e2etests/testlocalapps/http-headers/pom.xml | 2 +- e2etests/testlocalapps/java8-jar/pom.xml | 2 +- e2etests/testlocalapps/java8-no-webxml/pom.xml | 2 +- e2etests/testlocalapps/pom.xml | 2 +- e2etests/testlocalapps/sample-badaeweb/pom.xml | 2 +- .../testlocalapps/sample-baddispatch-yaml/pom.xml | 2 +- e2etests/testlocalapps/sample-baddispatch/pom.xml | 2 +- .../testlocalapps/sample-badentrypoint/pom.xml | 2 +- e2etests/testlocalapps/sample-badindexes/pom.xml | 2 +- .../testlocalapps/sample-badruntimechannel/pom.xml | 2 +- e2etests/testlocalapps/sample-badweb/pom.xml | 2 +- .../testlocalapps/sample-default-auto-ids/pom.xml | 2 +- .../testlocalapps/sample-error-in-tag-file/pom.xml | 2 +- e2etests/testlocalapps/sample-java11/pom.xml | 2 +- e2etests/testlocalapps/sample-java17/pom.xml | 2 +- .../testlocalapps/sample-jsptaglibrary/pom.xml | 2 +- e2etests/testlocalapps/sample-jspx/pom.xml | 2 +- .../testlocalapps/sample-legacy-auto-ids/pom.xml | 2 +- e2etests/testlocalapps/sample-missingappid/pom.xml | 2 +- e2etests/testlocalapps/sample-nojsps/pom.xml | 2 +- .../sample-unspecified-auto-ids/pom.xml | 2 +- e2etests/testlocalapps/sample-with-classes/pom.xml | 2 +- .../sampleapp-automatic-module/pom.xml | 2 +- e2etests/testlocalapps/sampleapp-backends/pom.xml | 2 +- .../testlocalapps/sampleapp-basic-module/pom.xml | 2 +- .../testlocalapps/sampleapp-manual-module/pom.xml | 2 +- e2etests/testlocalapps/sampleapp-runtime/pom.xml | 2 +- e2etests/testlocalapps/sampleapp/pom.xml | 2 +- e2etests/testlocalapps/stage-sampleapp/pom.xml | 2 +- .../stage-with-staging-options/pom.xml | 2 +- e2etests/testlocalapps/xmlorder/pom.xml | 2 +- external/geronimo_javamail/pom.xml | 2 +- .../api_compatibility_tests/pom.xml | 2 +- jetty12_assembly/pom.xml | 2 +- lib/pom.xml | 2 +- lib/tools_api/pom.xml | 2 +- lib/xml_validator/pom.xml | 2 +- lib/xml_validator_test/pom.xml | 2 +- local_runtime_shared_jetty12/pom.xml | 2 +- local_runtime_shared_jetty9/pom.xml | 2 +- pom.xml | 2 +- protobuf/pom.xml | 2 +- quickstartgenerator/pom.xml | 2 +- quickstartgenerator_jetty12/pom.xml | 2 +- quickstartgenerator_jetty12_ee10/pom.xml | 2 +- remoteapi/pom.xml | 2 +- runtime/annotationscanningwebapp/pom.xml | 2 +- runtime/deployment/pom.xml | 2 +- runtime/failinitfilterwebapp/pom.xml | 2 +- runtime/impl/pom.xml | 2 +- runtime/lite/pom.xml | 2 +- runtime/local_jetty12/pom.xml | 2 +- runtime/local_jetty12_ee10/pom.xml | 2 +- runtime/local_jetty9/pom.xml | 2 +- runtime/main/pom.xml | 2 +- runtime/nogaeapiswebapp/pom.xml | 2 +- runtime/pom.xml | 2 +- runtime/runtime_impl_jetty12/pom.xml | 2 +- runtime/runtime_impl_jetty9/pom.xml | 2 +- runtime/test/pom.xml | 2 +- runtime/testapps/pom.xml | 2 +- runtime/util/pom.xml | 2 +- runtime_shared/pom.xml | 2 +- runtime_shared_jetty12/pom.xml | 2 +- runtime_shared_jetty12_ee10/pom.xml | 2 +- runtime_shared_jetty9/pom.xml | 2 +- sdk_assembly/pom.xml | 2 +- sessiondata/pom.xml | 2 +- shared_sdk/pom.xml | 2 +- shared_sdk_jetty12/pom.xml | 2 +- shared_sdk_jetty9/pom.xml | 2 +- utils/pom.xml | 2 +- 112 files changed, 124 insertions(+), 124 deletions(-) diff --git a/README.md b/README.md index 824fa076c..69853c857 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Source code for all public APIs for com.google.appengine.api.* packages. com.google.appengine appengine-api-1.0-sdk - 2.0.27 + 2.0.28 javax.servlet @@ -89,7 +89,7 @@ Source code for all public APIs for com.google.appengine.api.* packages. com.google.appengine appengine-api-1.0-sdk - 2.0.27 + 2.0.28 javax.servlet @@ -188,7 +188,7 @@ Source code for remote APIs for App Engine. com.google.appengine appengine-remote-api - 2.0.27 + 2.0.28 ``` @@ -211,7 +211,7 @@ We moved `com.google.appengine.api.memcache.stdimpl` and its old dependency com.google.appengine appengine-api-legacy.jar/artifactId> - 2.0.27 + 2.0.28 ``` @@ -226,19 +226,19 @@ We moved `com.google.appengine.api.memcache.stdimpl` and its old dependency com.google.appengine appengine-testing - 2.0.27 + 2.0.28 test com.google.appengine appengine-api-stubs - 2.0.27 + 2.0.28 test com.google.appengine appengine-tools-sdk - 2.0.27 + 2.0.28 test ``` diff --git a/TRYLATESTBITSINPROD.md b/TRYLATESTBITSINPROD.md index 8d937eb1a..9f4a4eea7 100644 --- a/TRYLATESTBITSINPROD.md +++ b/TRYLATESTBITSINPROD.md @@ -46,12 +46,12 @@ top of your web application and change the entrypoint to boot with these jars in mvn clean install ``` -Let's assume the current built version is `2.0.28-SNAPSHOT`. +Let's assume the current built version is `2.0.29-SNAPSHOT`. Add the dependency for the GAE runtime jars in your application pom.xml file: ``` - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT target/${project.artifactId}-${project.version} ... diff --git a/api/pom.xml b/api/pom.xml index 87f1a692a..25544e889 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -21,7 +21,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT true @@ -239,7 +239,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.3 + 3.7.0 com.microsoft.doclet.DocFxDoclet false diff --git a/api_dev/pom.xml b/api_dev/pom.xml index 057f8ce52..203d807b0 100644 --- a/api_dev/pom.xml +++ b/api_dev/pom.xml @@ -23,7 +23,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/api_legacy/pom.xml b/api_legacy/pom.xml index 47d744cf6..3f57294f9 100644 --- a/api_legacy/pom.xml +++ b/api_legacy/pom.xml @@ -22,7 +22,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/appengine-api-1.0-sdk/pom.xml b/appengine-api-1.0-sdk/pom.xml index 6b59f9deb..7050400ee 100644 --- a/appengine-api-1.0-sdk/pom.xml +++ b/appengine-api-1.0-sdk/pom.xml @@ -20,7 +20,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar AppEngine :: appengine-api-1.0-sdk diff --git a/appengine-api-stubs/pom.xml b/appengine-api-stubs/pom.xml index 3f7a96fc4..efd0ea8e6 100644 --- a/appengine-api-stubs/pom.xml +++ b/appengine-api-stubs/pom.xml @@ -23,7 +23,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/appengine_init/pom.xml b/appengine_init/pom.xml index 3fe10f5b6..8128f855a 100644 --- a/appengine_init/pom.xml +++ b/appengine_init/pom.xml @@ -23,7 +23,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/appengine_jsr107/pom.xml b/appengine_jsr107/pom.xml index 5bf487b87..9f8b380ed 100644 --- a/appengine_jsr107/pom.xml +++ b/appengine_jsr107/pom.xml @@ -24,7 +24,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT diff --git a/appengine_resources/pom.xml b/appengine_resources/pom.xml index 227d12183..c73d8dc44 100644 --- a/appengine_resources/pom.xml +++ b/appengine_resources/pom.xml @@ -21,7 +21,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar AppEngine :: appengine-resources diff --git a/appengine_setup/apiserver_local/pom.xml b/appengine_setup/apiserver_local/pom.xml index 464b0a575..53dc6f281 100644 --- a/appengine_setup/apiserver_local/pom.xml +++ b/appengine_setup/apiserver_local/pom.xml @@ -20,7 +20,7 @@ com.google.appengine appengine_setup - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT 4.0.0 diff --git a/appengine_setup/pom.xml b/appengine_setup/pom.xml index 4fe52d1f5..931a69538 100644 --- a/appengine_setup/pom.xml +++ b/appengine_setup/pom.xml @@ -24,7 +24,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT apiserver_local diff --git a/appengine_setup/test/pom.xml b/appengine_setup/test/pom.xml index 2b3c12a02..1e7326595 100644 --- a/appengine_setup/test/pom.xml +++ b/appengine_setup/test/pom.xml @@ -20,7 +20,7 @@ com.google.appengine appengine_setup - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT 4.0.0 com.google.appengine diff --git a/appengine_setup/test/src/test/java/com/google/appengine/setup/test/Jetty12TestAppTest.java b/appengine_setup/test/src/test/java/com/google/appengine/setup/test/Jetty12TestAppTest.java index b841a0d06..ed745ebd0 100644 --- a/appengine_setup/test/src/test/java/com/google/appengine/setup/test/Jetty12TestAppTest.java +++ b/appengine_setup/test/src/test/java/com/google/appengine/setup/test/Jetty12TestAppTest.java @@ -26,6 +26,6 @@ protected String appName() { @Override protected String relativePathForUserApplicationJar() { return "../testapps/jetty12_testapp/target/" - + "jetty12_testapp-2.0.28-SNAPSHOT-jar-with-dependencies.jar"; + + "jetty12_testapp-2.0.29-SNAPSHOT-jar-with-dependencies.jar"; } } diff --git a/appengine_setup/test/src/test/java/com/google/appengine/setup/test/SpringBootTestAppTest.java b/appengine_setup/test/src/test/java/com/google/appengine/setup/test/SpringBootTestAppTest.java index df8590a8f..ab1d27c0d 100644 --- a/appengine_setup/test/src/test/java/com/google/appengine/setup/test/SpringBootTestAppTest.java +++ b/appengine_setup/test/src/test/java/com/google/appengine/setup/test/SpringBootTestAppTest.java @@ -25,6 +25,6 @@ protected String appName() { @Override protected String relativePathForUserApplicationJar() { - return "../testapps/springboot_testapp/target/" + "springboot_testapp-2.0.28-SNAPSHOT.jar"; + return "../testapps/springboot_testapp/target/" + "springboot_testapp-2.0.29-SNAPSHOT.jar"; } } diff --git a/appengine_setup/test/src/test/java/com/google/appengine/setup/test/util/TestUtil.java b/appengine_setup/test/src/test/java/com/google/appengine/setup/test/util/TestUtil.java index f7582607d..c6914d34d 100644 --- a/appengine_setup/test/src/test/java/com/google/appengine/setup/test/util/TestUtil.java +++ b/appengine_setup/test/src/test/java/com/google/appengine/setup/test/util/TestUtil.java @@ -62,7 +62,7 @@ public static HttpClient initializeHttpClient(int timeoutMillis) { @SneakyThrows public static Process initializeHttpApiServer() { String apiServerRelativeJarPath = - "../apiserver_local/target/" + "apiserver_local-2.0.28-SNAPSHOT-jar-with-dependencies.jar"; + "../apiserver_local/target/" + "apiserver_local-2.0.29-SNAPSHOT-jar-with-dependencies.jar"; File currentDirectory = new File("").getAbsoluteFile(); File apiServerJar = new File(currentDirectory, apiServerRelativeJarPath); ImmutableList processArgs = ImmutableList.builder() diff --git a/appengine_setup/testapps/jetty12_testapp/pom.xml b/appengine_setup/testapps/jetty12_testapp/pom.xml index f7e00cbc9..2c250e2f5 100644 --- a/appengine_setup/testapps/jetty12_testapp/pom.xml +++ b/appengine_setup/testapps/jetty12_testapp/pom.xml @@ -20,7 +20,7 @@ testapps com.google.appengine - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT 4.0.0 com.google.appengine.setup.testapps @@ -33,7 +33,7 @@ com.google.appengine.setup.testapps testapps_common - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT org.eclipse.jetty @@ -106,7 +106,7 @@ srirammahavadi-dev GCLOUD_CONFIG true - ${project.build.directory}/jetty11_testapp-2.0.28-SNAPSHOT-jar-with-dependencies.jar + ${project.build.directory}/jetty11_testapp-2.0.29-SNAPSHOT-jar-with-dependencies.jar diff --git a/appengine_setup/testapps/pom.xml b/appengine_setup/testapps/pom.xml index 31cc88b24..7a9ceb0ee 100644 --- a/appengine_setup/testapps/pom.xml +++ b/appengine_setup/testapps/pom.xml @@ -20,7 +20,7 @@ com.google.appengine appengine_setup - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT 4.0.0 com.google.appengine diff --git a/appengine_setup/testapps/springboot_testapp/pom.xml b/appengine_setup/testapps/springboot_testapp/pom.xml index 521c48886..645425fac 100644 --- a/appengine_setup/testapps/springboot_testapp/pom.xml +++ b/appengine_setup/testapps/springboot_testapp/pom.xml @@ -25,7 +25,7 @@ com.google.appengine.setup.testapps springboot_testapp - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT springboot_testapp Demo project for Spring Boot @@ -44,12 +44,12 @@ com.google.appengine appengine-api-1.0-sdk - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT com.google.appengine.setup.testapps testapps_common - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/appengine_setup/testapps/testapps_common/pom.xml b/appengine_setup/testapps/testapps_common/pom.xml index fbfe9082a..453dce47c 100644 --- a/appengine_setup/testapps/testapps_common/pom.xml +++ b/appengine_setup/testapps/testapps_common/pom.xml @@ -20,7 +20,7 @@ testapps com.google.appengine - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT 4.0.0 com.google.appengine.setup.testapps diff --git a/appengine_testing/pom.xml b/appengine_testing/pom.xml index d01756f89..bdf22a17c 100644 --- a/appengine_testing/pom.xml +++ b/appengine_testing/pom.xml @@ -23,7 +23,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/appengine_testing_tests/pom.xml b/appengine_testing_tests/pom.xml index 077391748..9e9abaf55 100644 --- a/appengine_testing_tests/pom.xml +++ b/appengine_testing_tests/pom.xml @@ -23,7 +23,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/applications/pom.xml b/applications/pom.xml index 35efc7510..02a1f0bc2 100644 --- a/applications/pom.xml +++ b/applications/pom.xml @@ -22,7 +22,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT pom diff --git a/applications/proberapp/pom.xml b/applications/proberapp/pom.xml index 1d51bc57d..f39d5b62b 100644 --- a/applications/proberapp/pom.xml +++ b/applications/proberapp/pom.xml @@ -27,7 +27,7 @@ com.google.appengine applications - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT diff --git a/applications/springboot/pom.xml b/applications/springboot/pom.xml index 7235d6700..a20b7bea2 100644 --- a/applications/springboot/pom.xml +++ b/applications/springboot/pom.xml @@ -24,7 +24,7 @@ com.google.appengine applications - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/devappservertests/pom.xml b/e2etests/devappservertests/pom.xml index 5424e4683..adb712da0 100644 --- a/e2etests/devappservertests/pom.xml +++ b/e2etests/devappservertests/pom.xml @@ -22,7 +22,7 @@ com.google.appengine e2etests - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/e2etests/pom.xml b/e2etests/pom.xml index 222b95de0..56217a3a0 100644 --- a/e2etests/pom.xml +++ b/e2etests/pom.xml @@ -23,7 +23,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT AppEngine :: e2e tests pom diff --git a/e2etests/stagingtests/pom.xml b/e2etests/stagingtests/pom.xml index 98badecbb..ad84260b7 100644 --- a/e2etests/stagingtests/pom.xml +++ b/e2etests/stagingtests/pom.xml @@ -22,7 +22,7 @@ com.google.appengine e2etests - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/e2etests/testlocalapps/allinone/pom.xml b/e2etests/testlocalapps/allinone/pom.xml index 148a3a361..fe21ddd06 100644 --- a/e2etests/testlocalapps/allinone/pom.xml +++ b/e2etests/testlocalapps/allinone/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/allinone_jakarta/pom.xml b/e2etests/testlocalapps/allinone_jakarta/pom.xml index a75ea6071..3615f5c53 100644 --- a/e2etests/testlocalapps/allinone_jakarta/pom.xml +++ b/e2etests/testlocalapps/allinone_jakarta/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/badcron/pom.xml b/e2etests/testlocalapps/badcron/pom.xml index 75d72820f..b5125568f 100644 --- a/e2etests/testlocalapps/badcron/pom.xml +++ b/e2etests/testlocalapps/badcron/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/bundle_standard/pom.xml b/e2etests/testlocalapps/bundle_standard/pom.xml index 0ddf03824..0817deee3 100644 --- a/e2etests/testlocalapps/bundle_standard/pom.xml +++ b/e2etests/testlocalapps/bundle_standard/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/bundle_standard_with_container_initializer/pom.xml b/e2etests/testlocalapps/bundle_standard_with_container_initializer/pom.xml index cffc1787d..5944bad9c 100644 --- a/e2etests/testlocalapps/bundle_standard_with_container_initializer/pom.xml +++ b/e2etests/testlocalapps/bundle_standard_with_container_initializer/pom.xml @@ -25,7 +25,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/bundle_standard_with_no_jsp/pom.xml b/e2etests/testlocalapps/bundle_standard_with_no_jsp/pom.xml index e345fc4a8..95f096f66 100644 --- a/e2etests/testlocalapps/bundle_standard_with_no_jsp/pom.xml +++ b/e2etests/testlocalapps/bundle_standard_with_no_jsp/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/bundle_standard_with_weblistener_memcache/pom.xml b/e2etests/testlocalapps/bundle_standard_with_weblistener_memcache/pom.xml index 9b3037d10..65cbdd2b3 100644 --- a/e2etests/testlocalapps/bundle_standard_with_weblistener_memcache/pom.xml +++ b/e2etests/testlocalapps/bundle_standard_with_weblistener_memcache/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/cron-bad-job-age-limit/pom.xml b/e2etests/testlocalapps/cron-bad-job-age-limit/pom.xml index 01c248a95..bab7551e0 100644 --- a/e2etests/testlocalapps/cron-bad-job-age-limit/pom.xml +++ b/e2etests/testlocalapps/cron-bad-job-age-limit/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/cron-good-retry-parameters/pom.xml b/e2etests/testlocalapps/cron-good-retry-parameters/pom.xml index 22f30dfe8..8b31d2e32 100644 --- a/e2etests/testlocalapps/cron-good-retry-parameters/pom.xml +++ b/e2etests/testlocalapps/cron-good-retry-parameters/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/cron-negative-max-backoff/pom.xml b/e2etests/testlocalapps/cron-negative-max-backoff/pom.xml index ec50eb466..ce96f93d6 100644 --- a/e2etests/testlocalapps/cron-negative-max-backoff/pom.xml +++ b/e2etests/testlocalapps/cron-negative-max-backoff/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/cron-negative-retry-limit/pom.xml b/e2etests/testlocalapps/cron-negative-retry-limit/pom.xml index 8f4351138..5f734c59f 100644 --- a/e2etests/testlocalapps/cron-negative-retry-limit/pom.xml +++ b/e2etests/testlocalapps/cron-negative-retry-limit/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/cron-two-max-doublings/pom.xml b/e2etests/testlocalapps/cron-two-max-doublings/pom.xml index baa5aa0a3..34f1e9ae6 100644 --- a/e2etests/testlocalapps/cron-two-max-doublings/pom.xml +++ b/e2etests/testlocalapps/cron-two-max-doublings/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/http-headers/pom.xml b/e2etests/testlocalapps/http-headers/pom.xml index 775ff63d9..b49f4bd75 100644 --- a/e2etests/testlocalapps/http-headers/pom.xml +++ b/e2etests/testlocalapps/http-headers/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/java8-jar/pom.xml b/e2etests/testlocalapps/java8-jar/pom.xml index f12420f83..e5af26ddd 100644 --- a/e2etests/testlocalapps/java8-jar/pom.xml +++ b/e2etests/testlocalapps/java8-jar/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/java8-no-webxml/pom.xml b/e2etests/testlocalapps/java8-no-webxml/pom.xml index 5715bee0d..cbeca5b4f 100644 --- a/e2etests/testlocalapps/java8-no-webxml/pom.xml +++ b/e2etests/testlocalapps/java8-no-webxml/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/pom.xml b/e2etests/testlocalapps/pom.xml index c93a49d84..6ef4ffadf 100644 --- a/e2etests/testlocalapps/pom.xml +++ b/e2etests/testlocalapps/pom.xml @@ -22,7 +22,7 @@ com.google.appengine e2etests - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT pom diff --git a/e2etests/testlocalapps/sample-badaeweb/pom.xml b/e2etests/testlocalapps/sample-badaeweb/pom.xml index a624a53d3..d7f4930cc 100644 --- a/e2etests/testlocalapps/sample-badaeweb/pom.xml +++ b/e2etests/testlocalapps/sample-badaeweb/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-baddispatch-yaml/pom.xml b/e2etests/testlocalapps/sample-baddispatch-yaml/pom.xml index eeb3c72b2..b13938050 100644 --- a/e2etests/testlocalapps/sample-baddispatch-yaml/pom.xml +++ b/e2etests/testlocalapps/sample-baddispatch-yaml/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-baddispatch/pom.xml b/e2etests/testlocalapps/sample-baddispatch/pom.xml index dcc0c674f..8780b89b7 100644 --- a/e2etests/testlocalapps/sample-baddispatch/pom.xml +++ b/e2etests/testlocalapps/sample-baddispatch/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-badentrypoint/pom.xml b/e2etests/testlocalapps/sample-badentrypoint/pom.xml index 305399c62..9ea70cb30 100644 --- a/e2etests/testlocalapps/sample-badentrypoint/pom.xml +++ b/e2etests/testlocalapps/sample-badentrypoint/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-badindexes/pom.xml b/e2etests/testlocalapps/sample-badindexes/pom.xml index e1ef0e231..69e6bceaf 100644 --- a/e2etests/testlocalapps/sample-badindexes/pom.xml +++ b/e2etests/testlocalapps/sample-badindexes/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-badruntimechannel/pom.xml b/e2etests/testlocalapps/sample-badruntimechannel/pom.xml index da7257a79..c715f7b61 100644 --- a/e2etests/testlocalapps/sample-badruntimechannel/pom.xml +++ b/e2etests/testlocalapps/sample-badruntimechannel/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-badweb/pom.xml b/e2etests/testlocalapps/sample-badweb/pom.xml index 713f3c53d..d844b3f17 100644 --- a/e2etests/testlocalapps/sample-badweb/pom.xml +++ b/e2etests/testlocalapps/sample-badweb/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-default-auto-ids/pom.xml b/e2etests/testlocalapps/sample-default-auto-ids/pom.xml index 88c8fed65..4daf5796f 100644 --- a/e2etests/testlocalapps/sample-default-auto-ids/pom.xml +++ b/e2etests/testlocalapps/sample-default-auto-ids/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-error-in-tag-file/pom.xml b/e2etests/testlocalapps/sample-error-in-tag-file/pom.xml index bdcf4e66c..c39523d1d 100644 --- a/e2etests/testlocalapps/sample-error-in-tag-file/pom.xml +++ b/e2etests/testlocalapps/sample-error-in-tag-file/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-java11/pom.xml b/e2etests/testlocalapps/sample-java11/pom.xml index c50af8be5..648df504b 100644 --- a/e2etests/testlocalapps/sample-java11/pom.xml +++ b/e2etests/testlocalapps/sample-java11/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-java17/pom.xml b/e2etests/testlocalapps/sample-java17/pom.xml index ac9c094c9..d40cafb62 100644 --- a/e2etests/testlocalapps/sample-java17/pom.xml +++ b/e2etests/testlocalapps/sample-java17/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-jsptaglibrary/pom.xml b/e2etests/testlocalapps/sample-jsptaglibrary/pom.xml index 6a004b396..2ade61b1c 100644 --- a/e2etests/testlocalapps/sample-jsptaglibrary/pom.xml +++ b/e2etests/testlocalapps/sample-jsptaglibrary/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-jspx/pom.xml b/e2etests/testlocalapps/sample-jspx/pom.xml index 3ca99a668..873102850 100644 --- a/e2etests/testlocalapps/sample-jspx/pom.xml +++ b/e2etests/testlocalapps/sample-jspx/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-legacy-auto-ids/pom.xml b/e2etests/testlocalapps/sample-legacy-auto-ids/pom.xml index 3429515f4..30432151e 100644 --- a/e2etests/testlocalapps/sample-legacy-auto-ids/pom.xml +++ b/e2etests/testlocalapps/sample-legacy-auto-ids/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-missingappid/pom.xml b/e2etests/testlocalapps/sample-missingappid/pom.xml index 72216b8ef..61b9650cb 100644 --- a/e2etests/testlocalapps/sample-missingappid/pom.xml +++ b/e2etests/testlocalapps/sample-missingappid/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-nojsps/pom.xml b/e2etests/testlocalapps/sample-nojsps/pom.xml index c799ac6f1..4898b6a74 100644 --- a/e2etests/testlocalapps/sample-nojsps/pom.xml +++ b/e2etests/testlocalapps/sample-nojsps/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-unspecified-auto-ids/pom.xml b/e2etests/testlocalapps/sample-unspecified-auto-ids/pom.xml index 695d46fc0..02f349831 100644 --- a/e2etests/testlocalapps/sample-unspecified-auto-ids/pom.xml +++ b/e2etests/testlocalapps/sample-unspecified-auto-ids/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sample-with-classes/pom.xml b/e2etests/testlocalapps/sample-with-classes/pom.xml index 24c5b92fd..d15a2f6e3 100644 --- a/e2etests/testlocalapps/sample-with-classes/pom.xml +++ b/e2etests/testlocalapps/sample-with-classes/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sampleapp-automatic-module/pom.xml b/e2etests/testlocalapps/sampleapp-automatic-module/pom.xml index dfa833388..eb3d42cb9 100644 --- a/e2etests/testlocalapps/sampleapp-automatic-module/pom.xml +++ b/e2etests/testlocalapps/sampleapp-automatic-module/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sampleapp-backends/pom.xml b/e2etests/testlocalapps/sampleapp-backends/pom.xml index 499f1fb68..460fa693f 100644 --- a/e2etests/testlocalapps/sampleapp-backends/pom.xml +++ b/e2etests/testlocalapps/sampleapp-backends/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war AppEngine :: sampleapp-backends diff --git a/e2etests/testlocalapps/sampleapp-basic-module/pom.xml b/e2etests/testlocalapps/sampleapp-basic-module/pom.xml index 474dae6d0..750ccb42c 100644 --- a/e2etests/testlocalapps/sampleapp-basic-module/pom.xml +++ b/e2etests/testlocalapps/sampleapp-basic-module/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sampleapp-manual-module/pom.xml b/e2etests/testlocalapps/sampleapp-manual-module/pom.xml index b23b323a0..2e8ef3c30 100644 --- a/e2etests/testlocalapps/sampleapp-manual-module/pom.xml +++ b/e2etests/testlocalapps/sampleapp-manual-module/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sampleapp-runtime/pom.xml b/e2etests/testlocalapps/sampleapp-runtime/pom.xml index d590195c6..12f39f0e6 100644 --- a/e2etests/testlocalapps/sampleapp-runtime/pom.xml +++ b/e2etests/testlocalapps/sampleapp-runtime/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/sampleapp/pom.xml b/e2etests/testlocalapps/sampleapp/pom.xml index 4727b36b5..5c2ec0951 100644 --- a/e2etests/testlocalapps/sampleapp/pom.xml +++ b/e2etests/testlocalapps/sampleapp/pom.xml @@ -25,7 +25,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT AppEngine :: sampleapp diff --git a/e2etests/testlocalapps/stage-sampleapp/pom.xml b/e2etests/testlocalapps/stage-sampleapp/pom.xml index 413c254d2..407119451 100644 --- a/e2etests/testlocalapps/stage-sampleapp/pom.xml +++ b/e2etests/testlocalapps/stage-sampleapp/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/stage-with-staging-options/pom.xml b/e2etests/testlocalapps/stage-with-staging-options/pom.xml index 17e13fbfb..1a614d55b 100644 --- a/e2etests/testlocalapps/stage-with-staging-options/pom.xml +++ b/e2etests/testlocalapps/stage-with-staging-options/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war diff --git a/e2etests/testlocalapps/xmlorder/pom.xml b/e2etests/testlocalapps/xmlorder/pom.xml index ce05d581a..45a3a1a01 100644 --- a/e2etests/testlocalapps/xmlorder/pom.xml +++ b/e2etests/testlocalapps/xmlorder/pom.xml @@ -24,7 +24,7 @@ com.google.appengine testlocalapps - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT war AppEngine :: xmlorder diff --git a/external/geronimo_javamail/pom.xml b/external/geronimo_javamail/pom.xml index c74eb1c41..4c690a0e1 100644 --- a/external/geronimo_javamail/pom.xml +++ b/external/geronimo_javamail/pom.xml @@ -22,7 +22,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT ../../pom.xml diff --git a/google3/third_party/java_src/appengine_standard/api_compatibility_tests/pom.xml b/google3/third_party/java_src/appengine_standard/api_compatibility_tests/pom.xml index e94e420da..3873065f4 100644 --- a/google3/third_party/java_src/appengine_standard/api_compatibility_tests/pom.xml +++ b/google3/third_party/java_src/appengine_standard/api_compatibility_tests/pom.xml @@ -22,7 +22,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/jetty12_assembly/pom.xml b/jetty12_assembly/pom.xml index dea1b3764..017111688 100644 --- a/jetty12_assembly/pom.xml +++ b/jetty12_assembly/pom.xml @@ -20,7 +20,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT 4.0.0 jetty12-assembly diff --git a/lib/pom.xml b/lib/pom.xml index 6bff51a6a..e0ece5cf9 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -22,7 +22,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT pom diff --git a/lib/tools_api/pom.xml b/lib/tools_api/pom.xml index baebdf60b..c45aa907c 100644 --- a/lib/tools_api/pom.xml +++ b/lib/tools_api/pom.xml @@ -23,7 +23,7 @@ com.google.appengine lib-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/lib/xml_validator/pom.xml b/lib/xml_validator/pom.xml index 10861bd3f..7d1caaaa2 100644 --- a/lib/xml_validator/pom.xml +++ b/lib/xml_validator/pom.xml @@ -22,7 +22,7 @@ com.google.appengine lib-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar AppEngine :: libxmlvalidator diff --git a/lib/xml_validator_test/pom.xml b/lib/xml_validator_test/pom.xml index 012a0f9d4..4206b8078 100644 --- a/lib/xml_validator_test/pom.xml +++ b/lib/xml_validator_test/pom.xml @@ -22,7 +22,7 @@ com.google.appengine lib-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar AppEngine :: libxmlvalidator_test diff --git a/local_runtime_shared_jetty12/pom.xml b/local_runtime_shared_jetty12/pom.xml index ad0ffb862..0f1087b84 100644 --- a/local_runtime_shared_jetty12/pom.xml +++ b/local_runtime_shared_jetty12/pom.xml @@ -21,7 +21,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar AppEngine :: appengine-local-runtime-shared Jetty12 diff --git a/local_runtime_shared_jetty9/pom.xml b/local_runtime_shared_jetty9/pom.xml index 59538ed2d..174a3c19b 100644 --- a/local_runtime_shared_jetty9/pom.xml +++ b/local_runtime_shared_jetty9/pom.xml @@ -21,7 +21,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar AppEngine :: appengine-local-runtime-shared Jetty9 diff --git a/pom.xml b/pom.xml index a3ec42786..0302e747b 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 4.0.0 com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT pom AppEngine :: Parent project diff --git a/protobuf/pom.xml b/protobuf/pom.xml index 28bcdae35..5fd6df8f6 100644 --- a/protobuf/pom.xml +++ b/protobuf/pom.xml @@ -23,7 +23,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/quickstartgenerator/pom.xml b/quickstartgenerator/pom.xml index cd3eab0d3..f54ebcc4a 100644 --- a/quickstartgenerator/pom.xml +++ b/quickstartgenerator/pom.xml @@ -23,7 +23,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/quickstartgenerator_jetty12/pom.xml b/quickstartgenerator_jetty12/pom.xml index 84c26eba0..a1f56d983 100644 --- a/quickstartgenerator_jetty12/pom.xml +++ b/quickstartgenerator_jetty12/pom.xml @@ -23,7 +23,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/quickstartgenerator_jetty12_ee10/pom.xml b/quickstartgenerator_jetty12_ee10/pom.xml index e88feed1c..f59f09baf 100644 --- a/quickstartgenerator_jetty12_ee10/pom.xml +++ b/quickstartgenerator_jetty12_ee10/pom.xml @@ -23,7 +23,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/remoteapi/pom.xml b/remoteapi/pom.xml index 5b820cedd..2141c0360 100644 --- a/remoteapi/pom.xml +++ b/remoteapi/pom.xml @@ -20,7 +20,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar AppEngine :: appengine-remote-api diff --git a/runtime/annotationscanningwebapp/pom.xml b/runtime/annotationscanningwebapp/pom.xml index ca634bd1b..05bcda902 100644 --- a/runtime/annotationscanningwebapp/pom.xml +++ b/runtime/annotationscanningwebapp/pom.xml @@ -23,7 +23,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT com.google.appengine.demos annotationscanningwebapp diff --git a/runtime/deployment/pom.xml b/runtime/deployment/pom.xml index df0d4e05d..a25137468 100644 --- a/runtime/deployment/pom.xml +++ b/runtime/deployment/pom.xml @@ -22,7 +22,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT pom diff --git a/runtime/failinitfilterwebapp/pom.xml b/runtime/failinitfilterwebapp/pom.xml index 93fb99634..eac631d82 100644 --- a/runtime/failinitfilterwebapp/pom.xml +++ b/runtime/failinitfilterwebapp/pom.xml @@ -23,7 +23,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT com.google.appengine.demos failinitfilterwebapp diff --git a/runtime/impl/pom.xml b/runtime/impl/pom.xml index 1a7215bc3..996fa6c0f 100644 --- a/runtime/impl/pom.xml +++ b/runtime/impl/pom.xml @@ -23,7 +23,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime/lite/pom.xml b/runtime/lite/pom.xml index 4fc592395..3c3f26bf9 100644 --- a/runtime/lite/pom.xml +++ b/runtime/lite/pom.xml @@ -23,7 +23,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime/local_jetty12/pom.xml b/runtime/local_jetty12/pom.xml index 864d865bf..4c1addf0c 100644 --- a/runtime/local_jetty12/pom.xml +++ b/runtime/local_jetty12/pom.xml @@ -23,7 +23,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime/local_jetty12_ee10/pom.xml b/runtime/local_jetty12_ee10/pom.xml index e66d220ab..957ca08a2 100644 --- a/runtime/local_jetty12_ee10/pom.xml +++ b/runtime/local_jetty12_ee10/pom.xml @@ -23,7 +23,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime/local_jetty9/pom.xml b/runtime/local_jetty9/pom.xml index 735783f4d..506742d17 100644 --- a/runtime/local_jetty9/pom.xml +++ b/runtime/local_jetty9/pom.xml @@ -23,7 +23,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime/main/pom.xml b/runtime/main/pom.xml index e520e6472..3da769847 100644 --- a/runtime/main/pom.xml +++ b/runtime/main/pom.xml @@ -23,7 +23,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime/nogaeapiswebapp/pom.xml b/runtime/nogaeapiswebapp/pom.xml index 4e9766cdb..dec193dc2 100644 --- a/runtime/nogaeapiswebapp/pom.xml +++ b/runtime/nogaeapiswebapp/pom.xml @@ -23,7 +23,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT com.google.appengine.demos nogaeapiswebapp diff --git a/runtime/pom.xml b/runtime/pom.xml index b23e2a77e..ee3dfde20 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -23,7 +23,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT AppEngine :: runtime projects pom diff --git a/runtime/runtime_impl_jetty12/pom.xml b/runtime/runtime_impl_jetty12/pom.xml index ea9b0665f..fc05747ba 100644 --- a/runtime/runtime_impl_jetty12/pom.xml +++ b/runtime/runtime_impl_jetty12/pom.xml @@ -23,7 +23,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime/runtime_impl_jetty9/pom.xml b/runtime/runtime_impl_jetty9/pom.xml index 6f52c368a..aecf372d7 100644 --- a/runtime/runtime_impl_jetty9/pom.xml +++ b/runtime/runtime_impl_jetty9/pom.xml @@ -23,7 +23,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime/test/pom.xml b/runtime/test/pom.xml index eda026aea..e4c411510 100644 --- a/runtime/test/pom.xml +++ b/runtime/test/pom.xml @@ -22,7 +22,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime/testapps/pom.xml b/runtime/testapps/pom.xml index bf52e7696..834a2846b 100644 --- a/runtime/testapps/pom.xml +++ b/runtime/testapps/pom.xml @@ -22,7 +22,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime/util/pom.xml b/runtime/util/pom.xml index c4ddcac05..d867bc722 100644 --- a/runtime/util/pom.xml +++ b/runtime/util/pom.xml @@ -22,7 +22,7 @@ com.google.appengine runtime-parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime_shared/pom.xml b/runtime_shared/pom.xml index 815ec9b3c..6c488a1a2 100644 --- a/runtime_shared/pom.xml +++ b/runtime_shared/pom.xml @@ -22,7 +22,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime_shared_jetty12/pom.xml b/runtime_shared_jetty12/pom.xml index 6ad5ed832..fec0b0152 100644 --- a/runtime_shared_jetty12/pom.xml +++ b/runtime_shared_jetty12/pom.xml @@ -22,7 +22,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime_shared_jetty12_ee10/pom.xml b/runtime_shared_jetty12_ee10/pom.xml index da43d0e33..123cd5b43 100644 --- a/runtime_shared_jetty12_ee10/pom.xml +++ b/runtime_shared_jetty12_ee10/pom.xml @@ -22,7 +22,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/runtime_shared_jetty9/pom.xml b/runtime_shared_jetty9/pom.xml index d74fd5693..e0ebea442 100644 --- a/runtime_shared_jetty9/pom.xml +++ b/runtime_shared_jetty9/pom.xml @@ -22,7 +22,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/sdk_assembly/pom.xml b/sdk_assembly/pom.xml index 4dc83b389..5cb1c2bfe 100644 --- a/sdk_assembly/pom.xml +++ b/sdk_assembly/pom.xml @@ -20,7 +20,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT 4.0.0 appengine-java-sdk diff --git a/sessiondata/pom.xml b/sessiondata/pom.xml index d08c9b45f..7ba9d6c3e 100644 --- a/sessiondata/pom.xml +++ b/sessiondata/pom.xml @@ -23,7 +23,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/shared_sdk/pom.xml b/shared_sdk/pom.xml index e2ab698d4..f89e82601 100644 --- a/shared_sdk/pom.xml +++ b/shared_sdk/pom.xml @@ -21,7 +21,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/shared_sdk_jetty12/pom.xml b/shared_sdk_jetty12/pom.xml index a8401ff94..5ad37beee 100644 --- a/shared_sdk_jetty12/pom.xml +++ b/shared_sdk_jetty12/pom.xml @@ -21,7 +21,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/shared_sdk_jetty9/pom.xml b/shared_sdk_jetty9/pom.xml index 4f57255f4..f6bad9cca 100644 --- a/shared_sdk_jetty9/pom.xml +++ b/shared_sdk_jetty9/pom.xml @@ -21,7 +21,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT jar diff --git a/utils/pom.xml b/utils/pom.xml index 80a8d53f1..354d12d4e 100644 --- a/utils/pom.xml +++ b/utils/pom.xml @@ -21,7 +21,7 @@ com.google.appengine parent - 2.0.28-SNAPSHOT + 2.0.29-SNAPSHOT true From 63df462b037527118421b1c49980a881c3de91fd Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 7 Jun 2024 00:42:34 +0000 Subject: [PATCH 02/28] Update dependency com.google.cloud:google-cloud-storage to v2.40.0 --- applications/proberapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/proberapp/pom.xml b/applications/proberapp/pom.xml index f39d5b62b..641f0e348 100644 --- a/applications/proberapp/pom.xml +++ b/applications/proberapp/pom.xml @@ -106,7 +106,7 @@ com.google.cloud google-cloud-storage - 2.39.0 + 2.40.0 com.google.cloud.sql From a58ee0fb107fa62b1bbc92c3841152e34d719ac8 Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Sat, 8 Jun 2024 04:45:54 -0700 Subject: [PATCH 03/28] expose the new background thread implementation to the RPC path for Java21 runtime only. Test has been added in the internal QA cluster. PiperOrigin-RevId: 641495925 Change-Id: Ifceaf9c187711dfd39b86d037595ed358ccef1e0 --- .../apphosting/runtime/RequestRunner.java | 74 +++++++++++++++---- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/runtime/impl/src/main/java/com/google/apphosting/runtime/RequestRunner.java b/runtime/impl/src/main/java/com/google/apphosting/runtime/RequestRunner.java index 7eff965d1..11a7ea6f1 100644 --- a/runtime/impl/src/main/java/com/google/apphosting/runtime/RequestRunner.java +++ b/runtime/impl/src/main/java/com/google/apphosting/runtime/RequestRunner.java @@ -18,6 +18,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; +import com.google.appengine.api.ThreadManager; import com.google.apphosting.api.ApiProxy; import com.google.apphosting.base.protos.HttpPb.ParsedHttpHeader; import com.google.apphosting.base.protos.RuntimePb.UPRequest; @@ -31,6 +32,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.time.Duration; +import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Exchanger; import java.util.concurrent.TimeoutException; @@ -235,22 +237,62 @@ private void dispatchRequest(RequestManager.RequestToken requestToken) throws Ex private void dispatchBackgroundRequest() throws InterruptedException, TimeoutException { String requestId = getBackgroundRequestId(upRequest); - // Wait here for synchronization with the ThreadFactory. - CountDownLatch latch = ThreadGroupPool.resetCurrentThread(); - Thread thread = new ThreadProxy(); - Runnable runnable = - coordinator.waitForUserRunnable( - requestId, thread, WAIT_FOR_USER_RUNNABLE_DEADLINE.toMillis()); - // Wait here until someone calls start() on the thread again. - latch.await(); - // Now set the context class loader to the UserClassLoader for the application - // and pass control to the Runnable the user provided. - ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(appVersion.getClassLoader()); - try { - runnable.run(); - } finally { - Thread.currentThread().setContextClassLoader(oldClassLoader); + // For java21 runtime, RPC path, do the new background thread handling for now, and keep it for + // other runtimes. + if (!Objects.equals(System.getenv("GAE_RUNTIME"), "java21")) { + // Wait here for synchronization with the ThreadFactory. + CountDownLatch latch = ThreadGroupPool.resetCurrentThread(); + Thread thread = new ThreadProxy(); + Runnable runnable = + coordinator.waitForUserRunnable( + requestId, thread, WAIT_FOR_USER_RUNNABLE_DEADLINE.toMillis()); + // Wait here until someone calls start() on the thread again. + latch.await(); + // Now set the context class loader to the UserClassLoader for the application + // and pass control to the Runnable the user provided. + ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(appVersion.getClassLoader()); + try { + runnable.run(); + } finally { + Thread.currentThread().setContextClassLoader(oldClassLoader); + } + } else { + // The interface of coordinator.waitForUserRunnable() requires us to provide the app code with + // a + // working thread *in the same exchange* where we get the runnable the user wants to run in + // the + // thread. This prevents us from actually directly feeding that runnable to the thread. To + // work + // around this conundrum, we create an EagerRunner, which lets us start running the thread + // without knowing yet what we want to run. + + // Create an ordinary request thread as a child of this background thread. + EagerRunner eagerRunner = new EagerRunner(); + Thread thread = ThreadManager.createThreadForCurrentRequest(eagerRunner); + + // Give this thread to the app code and get its desired runnable in response: + Runnable runnable = + coordinator.waitForUserRunnable( + requestId, thread, WAIT_FOR_USER_RUNNABLE_DEADLINE.toMillis()); + + // Finally, hand that runnable to the thread so it can actually start working. + // This will block until Thread.start() is called by the app code. This is by design: we must + // not exit this request handler until the thread has started *and* completed, otherwise the + // serving infrastructure will cancel our ability to make API calls. We're effectively + // "holding + // open the door" on the spawned thread's ability to make App Engine API calls. + // Now set the context class loader to the UserClassLoader for the application + // and pass control to the Runnable the user provided. + ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(appVersion.getClassLoader()); + try { + eagerRunner.supplyRunnable(runnable); + } finally { + Thread.currentThread().setContextClassLoader(oldClassLoader); + } + // Wait for the thread to end: + thread.join(); } upResponse.setError(UPResponse.ERROR.OK_VALUE); if (!upResponse.hasHttpResponse()) { From 6e0ad6a1b97cee0e9d75e29f124402a5b3840f19 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 9 Jun 2024 16:47:22 +0000 Subject: [PATCH 04/28] Update dependency org.easymock:easymock to v5.3.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0302e747b..da846e2c0 100644 --- a/pom.xml +++ b/pom.xml @@ -415,7 +415,7 @@ org.easymock easymock - 5.2.0 + 5.3.0 com.google.appengine From d9914a0600969b19afa00d832a8b2194c67d670e Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Mon, 10 Jun 2024 12:40:34 -0700 Subject: [PATCH 05/28] Group all automatic maven dep changes and run once a week. PiperOrigin-RevId: 641989917 Change-Id: I9550830795d0c601cab15e194a13bf5a97a83fc5 --- renovate.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index 72812ddaf..50a0af031 100644 --- a/renovate.json +++ b/renovate.json @@ -1,6 +1,6 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["config:recommended"], + "extends": ["config:recommended", "group:allNonMajor", "schedule:weekly"], "packageRules": [ { "matchPackageNames": [ From 098f1ddd4215ae50c68c55a45ddba277978f2d0b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 13 Jun 2024 12:35:36 -0700 Subject: [PATCH 06/28] Copybara import of the project: -- cad382ebb2efa8bb7ecc6858af7318e82af12d32 by Mend Renovate : Update all non-major dependencies COPYBARA_INTEGRATE_REVIEW=https://github.com/GoogleCloudPlatform/appengine-java-standard/pull/237 from renovate-bot:renovate/all-minor-patch cad382ebb2efa8bb7ecc6858af7318e82af12d32 PiperOrigin-RevId: 643087956 Change-Id: Ic6a90a5a7a06331ec9be8a4a580e93618eaf872f --- applications/proberapp/pom.xml | 4 ++-- jetty12_assembly/pom.xml | 2 +- pom.xml | 16 ++++++++-------- sdk_assembly/pom.xml | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/applications/proberapp/pom.xml b/applications/proberapp/pom.xml index 641f0e348..204a54122 100644 --- a/applications/proberapp/pom.xml +++ b/applications/proberapp/pom.xml @@ -58,7 +58,7 @@ com.google.cloud google-cloud-spanner - 6.68.1 + 6.69.0 com.google.api @@ -86,7 +86,7 @@ com.google.cloud google-cloud-bigquery - 2.40.2 + 2.40.3 com.google.cloud diff --git a/jetty12_assembly/pom.xml b/jetty12_assembly/pom.xml index 017111688..1c3f15b5b 100644 --- a/jetty12_assembly/pom.xml +++ b/jetty12_assembly/pom.xml @@ -36,7 +36,7 @@ maven-dependency-plugin - 3.6.1 + 3.7.0 unpack diff --git a/pom.xml b/pom.xml index da846e2c0..f65ef229c 100644 --- a/pom.xml +++ b/pom.xml @@ -671,42 +671,42 @@ io.netty netty-buffer - 4.1.110.Final + 4.1.111.Final io.netty netty-codec - 4.1.110.Final + 4.1.111.Final io.netty netty-codec-http - 4.1.110.Final + 4.1.111.Final io.netty netty-codec-http2 - 4.1.110.Final + 4.1.111.Final io.netty netty-common - 4.1.110.Final + 4.1.111.Final io.netty netty-handler - 4.1.110.Final + 4.1.111.Final io.netty netty-transport - 4.1.110.Final + 4.1.111.Final io.netty netty-transport-native-unix-common - 4.1.110.Final + 4.1.111.Final org.apache.tomcat diff --git a/sdk_assembly/pom.xml b/sdk_assembly/pom.xml index 5cb1c2bfe..d75ae46ee 100644 --- a/sdk_assembly/pom.xml +++ b/sdk_assembly/pom.xml @@ -81,7 +81,7 @@ maven-dependency-plugin - 3.6.1 + 3.7.0 unpack From d5ceffcb476aac9e804f1cdb35c9e7110503e1dc Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Fri, 14 Jun 2024 09:45:10 -0700 Subject: [PATCH 07/28] Rollback of Copybara import of the project: -- cad382ebb2efa8bb7ecc6858af7318e82af12d32 by Mend Renovate : Update all non-major dependencies PiperOrigin-RevId: 643373868 Change-Id: If2e006b72e040ad29fbee1a932ed1db61a204e41 --- pom.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index f65ef229c..da846e2c0 100644 --- a/pom.xml +++ b/pom.xml @@ -671,42 +671,42 @@ io.netty netty-buffer - 4.1.111.Final + 4.1.110.Final io.netty netty-codec - 4.1.111.Final + 4.1.110.Final io.netty netty-codec-http - 4.1.111.Final + 4.1.110.Final io.netty netty-codec-http2 - 4.1.111.Final + 4.1.110.Final io.netty netty-common - 4.1.111.Final + 4.1.110.Final io.netty netty-handler - 4.1.111.Final + 4.1.110.Final io.netty netty-transport - 4.1.111.Final + 4.1.110.Final io.netty netty-transport-native-unix-common - 4.1.111.Final + 4.1.110.Final org.apache.tomcat From 95545b08f5b25904f515566af3df64fe15b19c50 Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Mon, 17 Jun 2024 01:18:04 -0700 Subject: [PATCH 08/28] Update Maven dependencies for surefire plugin. PiperOrigin-RevId: 643911135 Change-Id: Ie95a644703ba134e23ec48548ff54dbede8ee0ac --- appengine_setup/apiserver_local/pom.xml | 2 +- pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/appengine_setup/apiserver_local/pom.xml b/appengine_setup/apiserver_local/pom.xml index 53dc6f281..feb8ecd4a 100644 --- a/appengine_setup/apiserver_local/pom.xml +++ b/appengine_setup/apiserver_local/pom.xml @@ -36,7 +36,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 org.apache.maven.plugins diff --git a/pom.xml b/pom.xml index da846e2c0..b79c8d100 100644 --- a/pom.xml +++ b/pom.xml @@ -208,7 +208,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 ../deployment/target/runtime-deployment-${project.version} @@ -234,7 +234,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 ../deployment/target/runtime-deployment-${project.version} From 990e1a71d2ad2fb59bf1752388c27d95b01bc808 Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Mon, 17 Jun 2024 03:23:30 -0700 Subject: [PATCH 09/28] Simplify io.netty maven version definition. Still need to understand why version 111 is not working... PiperOrigin-RevId: 643941786 Change-Id: I80f291f3fad1427d0ce4d23481baa4dfa5a88132 --- pom.xml | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/pom.xml b/pom.xml index b79c8d100..37e8da9bc 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,8 @@ UTF-8 9.4.54.v20240208 12.0.10 + 1.64.0 + 4.1.110.Final 2.0.13 https://oss.sonatype.org/content/repositories/google-snapshots/ sonatype-nexus-snapshots @@ -650,63 +652,63 @@ io.grpc grpc-api - 1.64.0 + ${io.grpc} io.grpc grpc-stub - 1.64.0 + ${io.grpc} io.grpc grpc-protobuf - 1.64.0 + ${io.grpc} io.grpc grpc-netty - 1.64.0 + ${io.grpc} io.netty netty-buffer - 4.1.110.Final + ${io.netty} io.netty netty-codec - 4.1.110.Final + ${io.netty} io.netty netty-codec-http - 4.1.110.Final + ${io.netty} io.netty netty-codec-http2 - 4.1.110.Final + ${io.netty} io.netty netty-common - 4.1.110.Final + ${io.netty} io.netty netty-handler - 4.1.110.Final + ${io.netty} io.netty netty-transport - 4.1.110.Final + ${io.netty} io.netty netty-transport-native-unix-common - 4.1.110.Final + ${io.netty} org.apache.tomcat From 5df937f51aef3f8aed1932da423af26cd3ec7890 Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Tue, 18 Jun 2024 00:07:13 -0700 Subject: [PATCH 10/28] Update maven version to 3.9.8 PiperOrigin-RevId: 644271271 Change-Id: I61e2aeeb7e846ee7bf7cf6c778aa274861c753d1 --- .mvn/wrapper/maven-wrapper.properties | 2 +- pom.xml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index fe97fa31d..ecbbc633c 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -15,4 +15,4 @@ # specific language governing permissions and limitations # under the License. wrapperVersion=3.3.1 -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.8/apache-maven-3.9.8-bin.zip diff --git a/pom.xml b/pom.xml index 37e8da9bc..6afab428f 100644 --- a/pom.xml +++ b/pom.xml @@ -567,7 +567,7 @@ org.apache.maven maven-core - 3.9.7 + 3.9.8 org.apache.ant @@ -583,7 +583,7 @@ org.apache.maven maven-plugin-api - 3.9.7 + 3.9.8 org.checkerframework @@ -842,7 +842,7 @@ org.apache.maven.plugins maven-release-plugin - 3.0.1 + 3.1.0 false deploy From 656a126e2a9544a5eaf89a166f4d7b675022b62a Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Fri, 21 Jun 2024 13:38:39 -0700 Subject: [PATCH 11/28] Update maven-jar-plugin version. PiperOrigin-RevId: 645487731 Change-Id: I090adea5de2188b9704162d1dfb6d381cfdc1fb0 --- runtime/lite/pom.xml | 2 +- runtime/runtime_impl_jetty12/pom.xml | 2 +- runtime/runtime_impl_jetty9/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/lite/pom.xml b/runtime/lite/pom.xml index 3c3f26bf9..6decabb1f 100644 --- a/runtime/lite/pom.xml +++ b/runtime/lite/pom.xml @@ -246,7 +246,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.4.1 + 3.4.2 diff --git a/runtime/runtime_impl_jetty12/pom.xml b/runtime/runtime_impl_jetty12/pom.xml index fc05747ba..58d610791 100644 --- a/runtime/runtime_impl_jetty12/pom.xml +++ b/runtime/runtime_impl_jetty12/pom.xml @@ -594,7 +594,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.4.1 + 3.4.2 diff --git a/runtime/runtime_impl_jetty9/pom.xml b/runtime/runtime_impl_jetty9/pom.xml index aecf372d7..19d3cb37f 100644 --- a/runtime/runtime_impl_jetty9/pom.xml +++ b/runtime/runtime_impl_jetty9/pom.xml @@ -483,7 +483,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.4.1 + 3.4.2 From 44e124acbdc6e728c452b80a0c6b487cbf23a937 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Wed, 26 Jun 2024 16:37:26 +1000 Subject: [PATCH 12/28] Add HttpConnector mode for Jetty9.4 runtimes. Signed-off-by: Lachlan Roberts --- .../runtime}/AppEngineConstants.java | 30 +- .../apphosting/runtime/JettyConstants.java | 40 -- .../apphosting/runtime/RequestAPIData.java | 2 + .../apphosting/runtime/RequestRunner.java | 2 +- .../apphosting/runtime/UpRequestAPIData.java | 12 + .../lite/BackgroundRequestDispatcher.java | 9 +- .../jetty/JettyServletEngineAdapter.java | 7 +- .../ee10/EE10AppVersionHandlerFactory.java | 8 +- .../jetty/ee10/ResourceFileServlet.java | 8 +- .../ee8/EE8AppVersionHandlerFactory.java | 8 +- .../jetty/ee8/ResourceFileServlet.java | 8 +- .../runtime/jetty/http/JettyHttpHandler.java | 19 +- .../jetty/http/JettyRequestAPIData.java | 79 +-- .../jetty/proxy/UPRequestTranslator.java | 66 +-- .../jetty9/AppVersionHandlerFactory.java | 50 +- .../runtime/jetty9/AppVersionHandlerMap.java | 4 +- .../runtime/jetty9/JettyHttpHandler.java | 286 ++++++++++ .../runtime/jetty9/JettyRequestAPIData.java | 501 ++++++++++++++++++ .../runtime/jetty9/JettyResponseAPIData.java | 90 ++++ .../runtime/jetty9/LocalRpcContext.java | 75 +++ .../runtime/jetty9/ResourceFileServlet.java | 8 +- .../runtime/jetty9/RpcConnection.java | 4 +- .../runtime/jetty9/UPRequestTranslator.java | 103 ++-- 23 files changed, 1190 insertions(+), 229 deletions(-) rename runtime/{runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty => impl/src/main/java/com/google/apphosting/runtime}/AppEngineConstants.java (78%) delete mode 100644 runtime/impl/src/main/java/com/google/apphosting/runtime/JettyConstants.java create mode 100644 runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpHandler.java create mode 100644 runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyRequestAPIData.java create mode 100644 runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyResponseAPIData.java create mode 100644 runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/LocalRpcContext.java diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/AppEngineConstants.java b/runtime/impl/src/main/java/com/google/apphosting/runtime/AppEngineConstants.java similarity index 78% rename from runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/AppEngineConstants.java rename to runtime/impl/src/main/java/com/google/apphosting/runtime/AppEngineConstants.java index 3136ce11c..89f0e7690 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/AppEngineConstants.java +++ b/runtime/impl/src/main/java/com/google/apphosting/runtime/AppEngineConstants.java @@ -14,11 +14,30 @@ * limitations under the License. */ -package com.google.apphosting.runtime.jetty; +package com.google.apphosting.runtime; import com.google.common.collect.ImmutableSet; +/** {@code AppEngineConstants} centralizes some constants that are specific to our use of Jetty. */ public final class AppEngineConstants { + /** + * This {@code ServletContext} attribute contains the {@link + * AppVersion} for the current application. + */ + public static final String APP_VERSION_CONTEXT_ATTR = + "com.google.apphosting.runtime.jetty.APP_VERSION_CONTEXT_ATTR"; + + /** + * This {@code ServletRequest} attribute contains the {@code + * AppVersionKey} identifying the current application. identify + * which application version to use. + */ + public static final String APP_VERSION_KEY_REQUEST_ATTR = + "com.google.apphosting.runtime.jetty.APP_VERSION_REQUEST_ATTR"; + + public static final String APP_YAML_ATTRIBUTE_TARGET = + "com.google.apphosting.runtime.jetty.appYaml"; + /** * The HTTP headers that are handled specially by this proxy are defined in lowercase because HTTP * headers are case-insensitive, and we look then up in a set or switch after converting to @@ -54,6 +73,11 @@ public final class AppEngineConstants { public static final String X_GOOGLE_INTERNAL_PROFILER = "x-google-internal-profiler"; public static final String X_CLOUD_TRACE_CONTEXT = "x-cloud-trace-context"; + public static final String X_APPENGINE_BACKGROUNDREQUEST = "x-appengine-backgroundrequest"; + public static final String BACKGROUND_REQUEST_URL = "/_ah/background"; + public static final String WARMUP_REQUEST_URL = "/_ah/start"; + public static final String BACKGROUND_REQUEST_SOURCE_IP = "0.1.0.3"; + public static final ImmutableSet PRIVATE_APPENGINE_HEADERS = ImmutableSet.of( X_APPENGINE_API_TICKET, @@ -83,7 +107,7 @@ public final class AppEngineConstants { "com.google.apphosting.internal.SkipAdminCheck"; // The impersonated IP address of warmup requests (and also background) - // () + // (https://g3doc.corp.google.com/apphosting/g3doc/howto/headers.md?cl=head) public static final String WARMUP_IP = "0.1.0.3"; public static final String DEFAULT_SECRET_KEY = "secretkey"; @@ -91,4 +115,6 @@ public final class AppEngineConstants { public static final String ENVIRONMENT_ATTR = "appengine.environment"; public static final String HTTP_CONNECTOR_MODE = "appengine.use.HttpConnector"; + + private AppEngineConstants() {} } diff --git a/runtime/impl/src/main/java/com/google/apphosting/runtime/JettyConstants.java b/runtime/impl/src/main/java/com/google/apphosting/runtime/JettyConstants.java deleted file mode 100644 index 7896f32d5..000000000 --- a/runtime/impl/src/main/java/com/google/apphosting/runtime/JettyConstants.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * 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 - * - * https://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.apphosting.runtime; - -/** {@code JettyConstants} centralizes some constants that are specific to our use of Jetty. */ -public final class JettyConstants { - /** - * This {@link ServletContext} attribute contains the {@link - * AppVersion} for the current application. - */ - public static final String APP_VERSION_CONTEXT_ATTR = - "com.google.apphosting.runtime.jetty.APP_VERSION_CONTEXT_ATTR"; - - /** - * This {@code ServletRequest} attribute contains the {@link - * AppVersionKey} identifying the current application. identify - * which application version to use. - */ - public static final String APP_VERSION_KEY_REQUEST_ATTR = - "com.google.apphosting.runtime.jetty.APP_VERSION_REQUEST_ATTR"; - - public static final String APP_YAML_ATTRIBUTE_TARGET = - "com.google.apphosting.runtime.jetty.appYaml"; - - private JettyConstants() {} -} diff --git a/runtime/impl/src/main/java/com/google/apphosting/runtime/RequestAPIData.java b/runtime/impl/src/main/java/com/google/apphosting/runtime/RequestAPIData.java index 7fad8ef29..8ede54464 100644 --- a/runtime/impl/src/main/java/com/google/apphosting/runtime/RequestAPIData.java +++ b/runtime/impl/src/main/java/com/google/apphosting/runtime/RequestAPIData.java @@ -84,4 +84,6 @@ public interface RequestAPIData { String getUrl(); RuntimePb.UPRequest.RequestType getRequestType(); + + String getBackgroundRequestId(); } diff --git a/runtime/impl/src/main/java/com/google/apphosting/runtime/RequestRunner.java b/runtime/impl/src/main/java/com/google/apphosting/runtime/RequestRunner.java index 11a7ea6f1..4c94829b9 100644 --- a/runtime/impl/src/main/java/com/google/apphosting/runtime/RequestRunner.java +++ b/runtime/impl/src/main/java/com/google/apphosting/runtime/RequestRunner.java @@ -154,7 +154,7 @@ public static boolean shouldKillCloneAfterException(Throwable th) { private String getBackgroundRequestId(UPRequest upRequest) { for (ParsedHttpHeader header : upRequest.getRequest().getHeadersList()) { - if (Ascii.equalsIgnoreCase(header.getKey(), "X-AppEngine-BackgroundRequest")) { + if (Ascii.equalsIgnoreCase(header.getKey(), AppEngineConstants.X_APPENGINE_BACKGROUNDREQUEST)) { return header.getValue(); } } diff --git a/runtime/impl/src/main/java/com/google/apphosting/runtime/UpRequestAPIData.java b/runtime/impl/src/main/java/com/google/apphosting/runtime/UpRequestAPIData.java index 9e80c17ab..9d87e0aab 100644 --- a/runtime/impl/src/main/java/com/google/apphosting/runtime/UpRequestAPIData.java +++ b/runtime/impl/src/main/java/com/google/apphosting/runtime/UpRequestAPIData.java @@ -19,6 +19,8 @@ import com.google.apphosting.base.protos.HttpPb; import com.google.apphosting.base.protos.RuntimePb; import com.google.apphosting.base.protos.TracePb; +import com.google.common.base.Ascii; + import java.util.stream.Stream; public class UpRequestAPIData implements RequestAPIData { @@ -178,4 +180,14 @@ public String getUrl() { public RuntimePb.UPRequest.RequestType getRequestType() { return request.getRequestType(); } + + @Override + public String getBackgroundRequestId() { + for (HttpPb.ParsedHttpHeader header : request.getRequest().getHeadersList()) { + if (Ascii.equalsIgnoreCase(header.getKey(), AppEngineConstants.X_APPENGINE_BACKGROUNDREQUEST)) { + return header.getValue(); + } + } + return null; + } } diff --git a/runtime/lite/src/main/java/com/google/appengine/runtime/lite/BackgroundRequestDispatcher.java b/runtime/lite/src/main/java/com/google/appengine/runtime/lite/BackgroundRequestDispatcher.java index a8e651b78..f3bb6cb28 100644 --- a/runtime/lite/src/main/java/com/google/appengine/runtime/lite/BackgroundRequestDispatcher.java +++ b/runtime/lite/src/main/java/com/google/appengine/runtime/lite/BackgroundRequestDispatcher.java @@ -16,6 +16,10 @@ package com.google.appengine.runtime.lite; +import static com.google.apphosting.runtime.AppEngineConstants.BACKGROUND_REQUEST_SOURCE_IP; +import static com.google.apphosting.runtime.AppEngineConstants.BACKGROUND_REQUEST_URL; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_BACKGROUNDREQUEST; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IP; import static java.util.concurrent.TimeUnit.MILLISECONDS; import com.google.appengine.api.ThreadManager; @@ -47,11 +51,6 @@ class BackgroundRequestDispatcher extends BackgroundRequestCoordinator { */ private static final Duration WAIT_FOR_USER_RUNNABLE_DEADLINE = Duration.ofSeconds(60); - private static final String X_APPENGINE_USER_IP = "x-appengine-user-ip"; - private static final String X_APPENGINE_BACKGROUNDREQUEST = "x-appengine-backgroundrequest"; - private static final String BACKGROUND_REQUEST_URL = "/_ah/background"; - private static final String BACKGROUND_REQUEST_SOURCE_IP = "0.1.0.3"; - public AbstractHandler createHandler() { return new BackgroundRequestHandler(); } diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java index efd995279..20557d100 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java @@ -21,8 +21,9 @@ import com.google.apphosting.base.protos.EmptyMessage; import com.google.apphosting.base.protos.RuntimePb.UPRequest; import com.google.apphosting.base.protos.RuntimePb.UPResponse; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.MutableUpResponse; import com.google.apphosting.runtime.ServletEngineAdapter; import com.google.apphosting.runtime.anyrpc.EvaluationRuntimeServerInterface; @@ -51,7 +52,7 @@ import java.util.Objects; import java.util.concurrent.ExecutionException; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.HTTP_CONNECTOR_MODE; +import static com.google.apphosting.runtime.AppEngineConstants.HTTP_CONNECTOR_MODE; import static java.nio.charset.StandardCharsets.UTF_8; /** @@ -269,7 +270,7 @@ public void serviceRequest(UPRequest upRequest, MutableUpResponse upResponse) th httpConfiguration.setUriCompliance(UriCompliance.LEGACY); } DelegateRpcExchange rpcExchange = new DelegateRpcExchange(upRequest, upResponse); - rpcExchange.setAttribute(JettyConstants.APP_VERSION_KEY_REQUEST_ATTR, appVersionKey); + rpcExchange.setAttribute(AppEngineConstants.APP_VERSION_KEY_REQUEST_ATTR, appVersionKey); rpcExchange.setAttribute(AppEngineConstants.ENVIRONMENT_ATTR, ApiProxy.getCurrentEnvironment()); rpcConnector.service(rpcExchange); try { diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/EE10AppVersionHandlerFactory.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/EE10AppVersionHandlerFactory.java index e64f98f35..fa1ee8195 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/EE10AppVersionHandlerFactory.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/EE10AppVersionHandlerFactory.java @@ -17,9 +17,9 @@ import com.google.apphosting.api.ApiProxy; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.SessionsConfig; -import com.google.apphosting.runtime.jetty.AppEngineConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.jetty.AppVersionHandlerFactory; import com.google.apphosting.runtime.jetty.EE10SessionManagerHandler; import com.google.common.flogger.GoogleLogger; @@ -53,7 +53,7 @@ import java.io.IOException; import java.io.PrintWriter; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.HTTP_CONNECTOR_MODE; +import static com.google.apphosting.runtime.AppEngineConstants.HTTP_CONNECTOR_MODE; /** * {@code AppVersionHandlerFactory} implements a {@code Handler} for a given {@code AppVersionKey}. @@ -191,7 +191,7 @@ private org.eclipse.jetty.server.Handler doCreateHandler(AppVersion appVersion) .setServletContextHandler(context); EE10SessionManagerHandler.create(builder.build()); // Pass the AppVersion on to any of our servlets (e.g. ResourceFileServlet). - context.setAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR, appVersion); + context.setAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR, appVersion); if (Boolean.getBoolean(HTTP_CONNECTOR_MODE)) { context.addEventListener( diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/ResourceFileServlet.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/ResourceFileServlet.java index 129190741..93c4f42d9 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/ResourceFileServlet.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/ResourceFileServlet.java @@ -17,7 +17,7 @@ package com.google.apphosting.runtime.jetty.ee10; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.utils.config.AppYaml; import com.google.common.base.Ascii; import com.google.common.flogger.GoogleLogger; @@ -71,11 +71,11 @@ public class ResourceFileServlet extends HttpServlet { public void init() throws ServletException { context = getServletContext(); AppVersion appVersion = - (AppVersion) context.getAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR); + (AppVersion) context.getAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR); chandler = ServletContextHandler.getServletContextHandler(context); AppYaml appYaml = - (AppYaml) chandler.getServer().getAttribute(JettyConstants.APP_YAML_ATTRIBUTE_TARGET); + (AppYaml) chandler.getServer().getAttribute(AppEngineConstants.APP_YAML_ATTRIBUTE_TARGET); fSender = new FileSender(appYaml); // AFAICT, there is no real API to retrieve this information, so // we access Jetty's internal state. @@ -261,7 +261,7 @@ private boolean maybeServeWelcomeFile( } AppVersion appVersion = - (AppVersion) getServletContext().getAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR); + (AppVersion) getServletContext().getAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR); ServletHandler handler = chandler.getServletHandler(); for (String welcomeName : welcomeFiles) { diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/EE8AppVersionHandlerFactory.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/EE8AppVersionHandlerFactory.java index 9c117306a..fcf3cf1ec 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/EE8AppVersionHandlerFactory.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/EE8AppVersionHandlerFactory.java @@ -18,9 +18,9 @@ import com.google.apphosting.api.ApiProxy; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.SessionsConfig; -import com.google.apphosting.runtime.jetty.AppEngineConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.jetty.AppVersionHandlerFactory; import com.google.apphosting.runtime.jetty.SessionManagerHandler; import com.google.common.flogger.GoogleLogger; @@ -46,7 +46,7 @@ import java.io.IOException; import java.io.PrintWriter; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.HTTP_CONNECTOR_MODE; +import static com.google.apphosting.runtime.AppEngineConstants.HTTP_CONNECTOR_MODE; /** * {@code AppVersionHandlerFactory} implements a {@code Handler} for a given {@code AppVersionKey}. @@ -205,7 +205,7 @@ private org.eclipse.jetty.server.Handler doCreateHandler(AppVersion appVersion) SessionManagerHandler.create(builder.build()); // Pass the AppVersion on to any of our servlets (e.g. ResourceFileServlet). - context.setAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR, appVersion); + context.setAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR, appVersion); if (Boolean.getBoolean(HTTP_CONNECTOR_MODE)) { context.addEventListener( diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/ResourceFileServlet.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/ResourceFileServlet.java index 2d949dd9b..f79c6ded5 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/ResourceFileServlet.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/ResourceFileServlet.java @@ -17,7 +17,7 @@ package com.google.apphosting.runtime.jetty.ee8; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.utils.config.AppYaml; import com.google.common.base.Ascii; import com.google.common.flogger.GoogleLogger; @@ -68,11 +68,11 @@ public class ResourceFileServlet extends HttpServlet { public void init() throws ServletException { context = getServletContext(); AppVersion appVersion = - (AppVersion) context.getAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR); + (AppVersion) context.getAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR); chandler = ContextHandler.getContextHandler(context); AppYaml appYaml = - (AppYaml) chandler.getServer().getAttribute(JettyConstants.APP_YAML_ATTRIBUTE_TARGET); + (AppYaml) chandler.getServer().getAttribute(AppEngineConstants.APP_YAML_ATTRIBUTE_TARGET); fSender = new FileSender(appYaml); // AFAICT, there is no real API to retrieve this information, so // we access Jetty's internal state. @@ -251,7 +251,7 @@ private boolean maybeServeWelcomeFile( } AppVersion appVersion = - (AppVersion) getServletContext().getAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR); + (AppVersion) getServletContext().getAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR); ServletHandler handler = chandler.getChildHandlerByClass(ServletHandler.class); MappedResource defaultEntry = handler.getHolderEntry("/"); diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyHttpHandler.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyHttpHandler.java index 64a357ce5..f188f0d0e 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyHttpHandler.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyHttpHandler.java @@ -24,13 +24,13 @@ import com.google.apphosting.runtime.ApiProxyImpl; import com.google.apphosting.runtime.AppVersion; import com.google.apphosting.runtime.BackgroundRequestCoordinator; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.RequestManager; import com.google.apphosting.runtime.RequestRunner; import com.google.apphosting.runtime.RequestRunner.EagerRunner; import com.google.apphosting.runtime.ResponseAPIData; import com.google.apphosting.runtime.ServletEngineAdapter; -import com.google.apphosting.runtime.jetty.AppEngineConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.jetty.AppInfoFactory; import com.google.common.base.Ascii; import com.google.common.flogger.GoogleLogger; @@ -49,8 +49,6 @@ import java.util.concurrent.TimeoutException; import static com.google.apphosting.runtime.RequestRunner.WAIT_FOR_USER_RUNNABLE_DEADLINE; -import java.util.concurrent.Exchanger; -import static java.util.concurrent.TimeUnit.MILLISECONDS; /** * This class replicates the behaviour of the {@link RequestRunner} for Requests which do not come @@ -168,7 +166,7 @@ private boolean dispatchServletRequest( throws Throwable { Request jettyRequest = request.getWrappedRequest(); Response jettyResponse = response.getWrappedResponse(); - jettyRequest.setAttribute(JettyConstants.APP_VERSION_KEY_REQUEST_ATTR, appVersionKey); + jettyRequest.setAttribute(AppEngineConstants.APP_VERSION_KEY_REQUEST_ATTR, appVersionKey); // Environment is set in a request attribute which is set/unset for async threads by // a ContextScopeListener created inside the AppVersionHandlerFactory. @@ -285,13 +283,10 @@ public static boolean shouldKillCloneAfterException(Throwable th) { } private String getBackgroundRequestId(JettyRequestAPIData upRequest) { - Optional match = - upRequest.getOriginalRequest().getHeaders().stream() - .filter(h -> Ascii.equalsIgnoreCase(h.getName(), "X-AppEngine-BackgroundRequest")) - .findFirst(); - if (match.isPresent()) { - return match.get().getValue(); + String backgroundRequestId = upRequest.getBackgroundRequestId(); + if (backgroundRequestId == null) { + throw new IllegalArgumentException("Did not receive a background request identifier."); } - throw new IllegalArgumentException("Did not receive a background request identifier."); + return backgroundRequestId; } } diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyRequestAPIData.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyRequestAPIData.java index 6c56ac139..88bb1daa9 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyRequestAPIData.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyRequestAPIData.java @@ -17,43 +17,46 @@ package com.google.apphosting.runtime.jetty.http; import static com.google.apphosting.base.protos.RuntimePb.UPRequest.RequestType.OTHER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.DEFAULT_SECRET_KEY; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.IS_ADMIN_HEADER_VALUE; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.IS_TRUSTED; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.PRIVATE_APPENGINE_HEADERS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.SKIP_ADMIN_CHECK_ATTR; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.WARMUP_IP; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_API_TICKET; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_APPSERVER_DATACENTER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_APPSERVER_TASK_BNS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_AUTH_DOMAIN; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_DEFAULT_VERSION_HOSTNAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_GAIA_AUTHUSER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_GAIA_ID; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_GAIA_SESSION; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_HTTPS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_ID_HASH; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_LOAS_PEER_USERNAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_QUEUENAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_REQUEST_LOG_ID; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_TIMEOUT_MS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_TRUSTED_IP_REQUEST; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_EMAIL; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_ID; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_IP; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_IS_ADMIN; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_ORGANIZATION; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_CLOUD_TRACE_CONTEXT; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_FORWARDED_PROTO; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_GOOGLE_INTERNAL_PROFILER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK; +import static com.google.apphosting.runtime.AppEngineConstants.BACKGROUND_REQUEST_URL; +import static com.google.apphosting.runtime.AppEngineConstants.DEFAULT_SECRET_KEY; +import static com.google.apphosting.runtime.AppEngineConstants.IS_ADMIN_HEADER_VALUE; +import static com.google.apphosting.runtime.AppEngineConstants.IS_TRUSTED; +import static com.google.apphosting.runtime.AppEngineConstants.PRIVATE_APPENGINE_HEADERS; +import static com.google.apphosting.runtime.AppEngineConstants.SKIP_ADMIN_CHECK_ATTR; +import static com.google.apphosting.runtime.AppEngineConstants.WARMUP_IP; +import static com.google.apphosting.runtime.AppEngineConstants.WARMUP_REQUEST_URL; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_API_TICKET; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_DATACENTER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_TASK_BNS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_AUTH_DOMAIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_BACKGROUNDREQUEST; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_DEFAULT_VERSION_HOSTNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_AUTHUSER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_SESSION; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_HTTPS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_ID_HASH; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_LOAS_PEER_USERNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_QUEUENAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_REQUEST_LOG_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TIMEOUT_MS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TRUSTED_IP_REQUEST; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_EMAIL; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IP; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IS_ADMIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ORGANIZATION; +import static com.google.apphosting.runtime.AppEngineConstants.X_CLOUD_TRACE_CONTEXT; +import static com.google.apphosting.runtime.AppEngineConstants.X_FORWARDED_PROTO; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_PROFILER; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK; import com.google.apphosting.base.protos.HttpPb; import com.google.apphosting.base.protos.RuntimePb; import com.google.apphosting.base.protos.TracePb; import com.google.apphosting.runtime.RequestAPIData; import com.google.apphosting.runtime.TraceContextHelper; -import com.google.apphosting.runtime.jetty.AppEngineConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.jetty.AppInfoFactory; import com.google.common.base.Strings; import com.google.common.flogger.GoogleLogger; @@ -103,6 +106,7 @@ public class JettyRequestAPIData implements RequestAPIData { private String defaultVersionHostname; private String email = ""; private String securityTicket; + private String backgroundRequestId; public JettyRequestAPIData( Request request, AppInfoFactory appInfoFactory, boolean passThroughPrivateHeaders) { @@ -216,6 +220,10 @@ public JettyRequestAPIData( */ break; + case X_APPENGINE_BACKGROUNDREQUEST: + backgroundRequestId = value; + break; + default: break; } @@ -237,11 +245,11 @@ public JettyRequestAPIData( } String decodedPath = request.getHttpURI().getDecodedPath(); - if ("/_ah/background".equals(decodedPath)) { + if (BACKGROUND_REQUEST_URL.equals(decodedPath)) { if (WARMUP_IP.equals(userIp)) { requestType = RuntimePb.UPRequest.RequestType.BACKGROUND; } - } else if ("/_ah/start".equals(decodedPath)) { + } else if (WARMUP_REQUEST_URL.equals(decodedPath)) { if (WARMUP_IP.equals(userIp)) { // This request came from within App Engine via secure internal channels; tell Jetty // it's HTTPS to avoid 403 because of web.xml security-constraint checks. @@ -310,6 +318,11 @@ public RuntimePb.UPRequest.RequestType getRequestType() { return requestType; } + @Override + public String getBackgroundRequestId() { + return backgroundRequestId; + } + @Override public boolean hasTraceContext() { return traceContext != null; diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/UPRequestTranslator.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/UPRequestTranslator.java index ee2d5d66e..02c49757a 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/UPRequestTranslator.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/UPRequestTranslator.java @@ -16,36 +16,38 @@ package com.google.apphosting.runtime.jetty.proxy; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.DEFAULT_SECRET_KEY; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.IS_ADMIN_HEADER_VALUE; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.IS_TRUSTED; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.PRIVATE_APPENGINE_HEADERS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.WARMUP_IP; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_API_TICKET; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_APPSERVER_DATACENTER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_APPSERVER_TASK_BNS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_AUTH_DOMAIN; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_DEFAULT_VERSION_HOSTNAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_GAIA_AUTHUSER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_GAIA_ID; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_GAIA_SESSION; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_HTTPS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_LOAS_PEER_USERNAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_QUEUENAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_REQUEST_LOG_ID; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_TIMEOUT_MS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_TRUSTED_IP_REQUEST; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_EMAIL; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_ID; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_IP; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_IS_ADMIN; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_NICKNAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_ORGANIZATION; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_CLOUD_TRACE_CONTEXT; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_FORWARDED_PROTO; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_GOOGLE_INTERNAL_PROFILER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK_UC; +import static com.google.apphosting.runtime.AppEngineConstants.BACKGROUND_REQUEST_URL; +import static com.google.apphosting.runtime.AppEngineConstants.DEFAULT_SECRET_KEY; +import static com.google.apphosting.runtime.AppEngineConstants.IS_ADMIN_HEADER_VALUE; +import static com.google.apphosting.runtime.AppEngineConstants.IS_TRUSTED; +import static com.google.apphosting.runtime.AppEngineConstants.PRIVATE_APPENGINE_HEADERS; +import static com.google.apphosting.runtime.AppEngineConstants.WARMUP_IP; +import static com.google.apphosting.runtime.AppEngineConstants.WARMUP_REQUEST_URL; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_API_TICKET; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_DATACENTER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_TASK_BNS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_AUTH_DOMAIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_DEFAULT_VERSION_HOSTNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_AUTHUSER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_SESSION; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_HTTPS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_LOAS_PEER_USERNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_QUEUENAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_REQUEST_LOG_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TIMEOUT_MS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TRUSTED_IP_REQUEST; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_EMAIL; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IP; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IS_ADMIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_NICKNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ORGANIZATION; +import static com.google.apphosting.runtime.AppEngineConstants.X_CLOUD_TRACE_CONTEXT; +import static com.google.apphosting.runtime.AppEngineConstants.X_FORWARDED_PROTO; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_PROFILER; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK_UC; import com.google.apphosting.base.protos.AppinfoPb; import com.google.apphosting.base.protos.HttpPb; @@ -181,11 +183,11 @@ public final RuntimePb.UPRequest translateRequest(Request jettyRequest) { } String decodedPath = jettyRequest.getHttpURI().getDecodedPath(); - if ("/_ah/background".equals(decodedPath)) { + if (BACKGROUND_REQUEST_URL.equals(decodedPath)) { if (WARMUP_IP.equals(httpRequest.getUserIp())) { upReqBuilder.setRequestType(UPRequest.RequestType.BACKGROUND); } - } else if ("/_ah/start".equals(decodedPath)) { + } else if (WARMUP_REQUEST_URL.equals(decodedPath)) { if (WARMUP_IP.equals(httpRequest.getUserIp())) { // This request came from within App Engine via secure internal channels; tell Jetty // it's HTTPS to avoid 403 because of web.xml security-constraint checks. diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerFactory.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerFactory.java index b47d25a3b..cf4696847 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerFactory.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerFactory.java @@ -16,13 +16,23 @@ package com.google.apphosting.runtime.jetty9; +import com.google.apphosting.api.ApiProxy; import com.google.apphosting.base.AppVersionKey; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.SessionsConfig; import com.google.common.collect.ImmutableList; import com.google.common.flogger.GoogleLogger; import com.google.common.html.HtmlEscapers; +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.UnavailableException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.jsp.JspFactory; import org.eclipse.jetty.annotations.AnnotationConfiguration; import org.eclipse.jetty.server.Dispatcher; import org.eclipse.jetty.server.Handler; @@ -33,16 +43,8 @@ import org.eclipse.jetty.webapp.MetaInfConfiguration; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebXmlConfiguration; +import org.eclipse.jetty.server.handler.ContextHandler; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; -import javax.servlet.UnavailableException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.jsp.JspFactory; -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; /** * {@code AppVersionHandlerFactory} implements a {@code Handler} for a given {@code AppVersionKey}. @@ -200,7 +202,33 @@ private Handler doCreateHandler(AppVersion appVersion) throws ServletException { SessionManagerHandler unused = SessionManagerHandler.create(builder.build()); // Pass the AppVersion on to any of our servlets (e.g. ResourceFileServlet). - context.setAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR, appVersion); + context.setAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR, appVersion); + if (Boolean.getBoolean(AppEngineConstants.HTTP_CONNECTOR_MODE)) { + context.addEventListener( + new ContextHandler.ContextScopeListener() { + @Override + public void enterScope( + ContextHandler.Context context, + org.eclipse.jetty.server.Request request, + Object reason) { + if (request != null) { + ApiProxy.Environment environment = + (ApiProxy.Environment) request.getAttribute(AppEngineConstants.ENVIRONMENT_ATTR); + if (environment != null) { + ApiProxy.setEnvironmentForCurrentThread(environment); + } + } + } + + @Override + public void exitScope( + ContextHandler.Context context, org.eclipse.jetty.server.Request request) { + if (request != null) { + ApiProxy.clearEnvironmentForCurrentThread(); + } + } + }); + } context.start(); // Check to see if servlet filter initialization failed. diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerMap.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerMap.java index 9a2b7d191..5d63b6a6d 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerMap.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerMap.java @@ -18,7 +18,7 @@ import com.google.apphosting.base.AppVersionKey; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.SessionStore; import com.google.apphosting.runtime.SessionStoreFactory; import org.eclipse.jetty.server.Handler; @@ -104,7 +104,7 @@ public void handle( String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { AppVersionKey appVersionKey = - (AppVersionKey) request.getAttribute(JettyConstants.APP_VERSION_KEY_REQUEST_ATTR); + (AppVersionKey) request.getAttribute(AppEngineConstants.APP_VERSION_KEY_REQUEST_ATTR); if (appVersionKey == null) { throw new ServletException("Request did not provide an application version"); } diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpHandler.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpHandler.java new file mode 100644 index 000000000..98e52235c --- /dev/null +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpHandler.java @@ -0,0 +1,286 @@ +/* + * Copyright 2021 Google LLC + * + * 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 + * + * https://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.apphosting.runtime.jetty9; + +import static com.google.apphosting.runtime.RequestRunner.WAIT_FOR_USER_RUNNABLE_DEADLINE; + +import com.google.appengine.api.ThreadManager; +import com.google.apphosting.api.ApiProxy; +import com.google.apphosting.base.AppVersionKey; +import com.google.apphosting.base.protos.EmptyMessage; +import com.google.apphosting.base.protos.RuntimePb; +import com.google.apphosting.runtime.ApiProxyImpl; +import com.google.apphosting.runtime.AppVersion; +import com.google.apphosting.runtime.BackgroundRequestCoordinator; +import com.google.apphosting.runtime.AppEngineConstants; +import com.google.apphosting.runtime.RequestManager; +import com.google.apphosting.runtime.RequestRunner; +import com.google.apphosting.runtime.RequestRunner.EagerRunner; +import com.google.apphosting.runtime.ResponseAPIData; +import com.google.apphosting.runtime.ServletEngineAdapter; +import com.google.common.flogger.GoogleLogger; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.time.Duration; +import java.util.concurrent.TimeoutException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.HandlerWrapper; + +/** + * This class replicates the behaviour of the {@link RequestRunner} for Requests which do not come + * through RPC. It should be added as a {@link Handler} to the Jetty {@link Server} wrapping the + * {@code AppEngineWebAppContext}. + * + *

This uses the {@link RequestManager} to start any AppEngine state associated with this request + * including the {@link ApiProxy.Environment} which it sets as a request attribute at {@link + * AppEngineConstants#ENVIRONMENT_ATTR}. This request attribute is pulled out by {@code + * ContextScopeListener}s installed by the {@code AppVersionHandlerFactory} implementations so that + * the {@link ApiProxy.Environment} is available all threads which are used to handle the request. + */ +public class JettyHttpHandler extends HandlerWrapper { + private static final GoogleLogger logger = GoogleLogger.forEnclosingClass(); + + private final boolean passThroughPrivateHeaders; + private final AppInfoFactory appInfoFactory; + private final AppVersionKey appVersionKey; + private final AppVersion appVersion; + private final RequestManager requestManager; + private final BackgroundRequestCoordinator coordinator; + + public JettyHttpHandler( + ServletEngineAdapter.Config runtimeOptions, + AppVersion appVersion, + AppVersionKey appVersionKey, + AppInfoFactory appInfoFactory) { + this.passThroughPrivateHeaders = runtimeOptions.passThroughPrivateHeaders(); + this.appInfoFactory = appInfoFactory; + this.appVersionKey = appVersionKey; + this.appVersion = appVersion; + + ApiProxyImpl apiProxyImpl = (ApiProxyImpl) ApiProxy.getDelegate(); + coordinator = apiProxyImpl.getBackgroundRequestCoordinator(); + requestManager = (RequestManager) apiProxyImpl.getRequestThreadManager(); + } + + @Override + public void handle( + String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { + + JettyRequestAPIData genericRequest = + new JettyRequestAPIData(baseRequest, request, appInfoFactory, passThroughPrivateHeaders); + JettyResponseAPIData genericResponse = new JettyResponseAPIData(baseRequest.getResponse(), response); + + // Read time remaining in request from headers and pass value to LocalRpcContext for use in + // reporting remaining time until deadline for API calls (see b/154745969) + Duration timeRemaining = genericRequest.getTimeRemaining(); + + ThreadGroup currentThreadGroup = Thread.currentThread().getThreadGroup(); + LocalRpcContext context = + new LocalRpcContext<>(EmptyMessage.class, timeRemaining); + RequestManager.RequestToken requestToken = + requestManager.startRequest( + appVersion, context, genericRequest, genericResponse, currentThreadGroup); + + // Set the environment as a request attribute, so it can be pulled out and set for async + // threads. + ApiProxy.Environment currentEnvironment = ApiProxy.getCurrentEnvironment(); + request.setAttribute(AppEngineConstants.ENVIRONMENT_ATTR, currentEnvironment); + + try { + dispatchRequest(target, requestToken, genericRequest, genericResponse); + if (!baseRequest.isHandled()) { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "request not handled"); + } + } catch ( + @SuppressWarnings("InterruptedExceptionSwallowed") + Throwable ex) { + // Note we do intentionally swallow InterruptException. + // We will report the exception via the rpc. We don't mark this thread as interrupted because + // ThreadGroupPool would use that as a signal to remove the thread from the pool; we don't + // need that. + handleException(ex, requestToken, genericResponse); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getMessage()); + } finally { + requestManager.finishRequest(requestToken); + } + // Do not put this in a final block. If we propagate an + // exception the callback will be invoked automatically. + genericResponse.finishWithResponse(context); + // We don't want threads used for background requests to go back + // in the thread pool, because users may have stashed references + // to them or may be expecting them to exit. Setting the + // interrupt bit causes the pool to drop them. + if (genericRequest.getRequestType() == RuntimePb.UPRequest.RequestType.BACKGROUND) { + Thread.currentThread().interrupt(); + } + } + + private boolean dispatchRequest( + String target, + RequestManager.RequestToken requestToken, + JettyRequestAPIData request, + JettyResponseAPIData response) + throws Throwable { + switch (request.getRequestType()) { + case SHUTDOWN: + logger.atInfo().log("Shutting down requests"); + requestManager.shutdownRequests(requestToken); + request.getBaseRequest().setHandled(true); + case BACKGROUND: + dispatchBackgroundRequest(request, response); + request.getBaseRequest().setHandled(true); + case OTHER: + dispatchServletRequest(target, request, response); + default: + throw new IllegalStateException(request.getRequestType().toString()); + } + } + + private void dispatchServletRequest( + String target, JettyRequestAPIData request, JettyResponseAPIData response) + throws Throwable { + Request baseRequest = request.getBaseRequest(); + HttpServletRequest httpServletRequest = request.getHttpServletRequest(); + HttpServletResponse httpServletResponse = response.getHttpServletResponse(); + baseRequest.setAttribute(AppEngineConstants.APP_VERSION_KEY_REQUEST_ATTR, appVersionKey); + + // Environment is set in a request attribute which is set/unset for async threads by + // a ContextScopeListener created inside the AppVersionHandlerFactory. + super.handle(target, baseRequest, httpServletRequest, httpServletResponse); + } + + private void dispatchBackgroundRequest(JettyRequestAPIData request, JettyResponseAPIData response) + throws InterruptedException, TimeoutException { + String requestId = getBackgroundRequestId(request); + // The interface of coordinator.waitForUserRunnable() requires us to provide the app code with a + // working thread *in the same exchange* where we get the runnable the user wants to run in the + // thread. This prevents us from actually directly feeding that runnable to the thread. To work + // around this conundrum, we create an EagerRunner, which lets us start running the thread + // without knowing yet what we want to run. + + // Create an ordinary request thread as a child of this background thread. + EagerRunner eagerRunner = new EagerRunner(); + Thread thread = ThreadManager.createThreadForCurrentRequest(eagerRunner); + + // Give this thread to the app code and get its desired runnable in response: + Runnable runnable = + coordinator.waitForUserRunnable( + requestId, thread, WAIT_FOR_USER_RUNNABLE_DEADLINE.toMillis()); + + // Finally, hand that runnable to the thread so it can actually start working. + // This will block until Thread.start() is called by the app code. This is by design: we must + // not exit this request handler until the thread has started *and* completed, otherwise the + // serving infrastructure will cancel our ability to make API calls. We're effectively "holding + // open the door" on the spawned thread's ability to make App Engine API calls. + // Now set the context class loader to the UserClassLoader for the application + // and pass control to the Runnable the user provided. + ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(appVersion.getClassLoader()); + try { + eagerRunner.supplyRunnable(runnable); + } finally { + Thread.currentThread().setContextClassLoader(oldClassLoader); + } + // Wait for the thread to end: + thread.join(); + } + + private boolean handleException( + Throwable ex, RequestManager.RequestToken requestToken, ResponseAPIData response) { + // Unwrap ServletException, either from javax or from jakarta exception: + try { + java.lang.reflect.Method getRootCause = ex.getClass().getMethod("getRootCause"); + Object rootCause = getRootCause.invoke(ex); + if (rootCause != null) { + ex = (Throwable) rootCause; + } + } catch (Throwable ignore) { + } + String msg = "Uncaught exception from servlet"; + logger.atWarning().withCause(ex).log("%s", msg); + // Don't use ApiProxy here, because we don't know what state the + // environment/delegate are in. + requestToken.addAppLogMessage(ApiProxy.LogRecord.Level.fatal, formatLogLine(msg, ex)); + + if (shouldKillCloneAfterException(ex)) { + logger.atSevere().log("Detected a dangerous exception, shutting down clone nicely."); + response.setTerminateClone(true); + } + RuntimePb.UPResponse.ERROR error = RuntimePb.UPResponse.ERROR.APP_FAILURE; + setFailure(response, error, "Unexpected exception from servlet: " + ex); + return true; + } + + /** Create a failure response from the given code and message. */ + public static void setFailure( + ResponseAPIData response, RuntimePb.UPResponse.ERROR error, String message) { + logger.atWarning().log("Runtime failed: %s, %s", error, message); + // If the response is already set, use that -- it's probably more + // specific (e.g. THREADS_STILL_RUNNING). + if (response.getError() == RuntimePb.UPResponse.ERROR.OK_VALUE) { + response.error(error.getNumber(), message); + } + } + + private String formatLogLine(String message, Throwable ex) { + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + printWriter.println(message); + ex.printStackTrace(printWriter); + return stringWriter.toString(); + } + + public static boolean shouldKillCloneAfterException(Throwable th) { + while (th != null) { + if (th instanceof OutOfMemoryError) { + return true; + } + try { + Throwable[] suppressed = th.getSuppressed(); + if (suppressed != null) { + for (Throwable s : suppressed) { + if (shouldKillCloneAfterException(s)) { + return true; + } + } + } + } catch (OutOfMemoryError ex) { + return true; + } + // TODO: Consider checking for other subclasses of + // VirtualMachineError, but probably not StackOverflowError. + th = th.getCause(); + } + return false; + } + + private String getBackgroundRequestId(JettyRequestAPIData upRequest) { + String backgroundRequestId = upRequest.getBackgroundRequestId(); + if (backgroundRequestId == null) { + throw new IllegalArgumentException("Did not receive a background request identifier."); + } + return backgroundRequestId; + } +} diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyRequestAPIData.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyRequestAPIData.java new file mode 100644 index 000000000..08f6cefa7 --- /dev/null +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyRequestAPIData.java @@ -0,0 +1,501 @@ +/* + * Copyright 2021 Google LLC + * + * 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 + * + * https://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.apphosting.runtime.jetty9; + +import static com.google.apphosting.base.protos.RuntimePb.UPRequest.RequestType.OTHER; +import static com.google.apphosting.runtime.AppEngineConstants.BACKGROUND_REQUEST_URL; +import static com.google.apphosting.runtime.AppEngineConstants.DEFAULT_SECRET_KEY; +import static com.google.apphosting.runtime.AppEngineConstants.IS_ADMIN_HEADER_VALUE; +import static com.google.apphosting.runtime.AppEngineConstants.IS_TRUSTED; +import static com.google.apphosting.runtime.AppEngineConstants.PRIVATE_APPENGINE_HEADERS; +import static com.google.apphosting.runtime.AppEngineConstants.SKIP_ADMIN_CHECK_ATTR; +import static com.google.apphosting.runtime.AppEngineConstants.WARMUP_IP; +import static com.google.apphosting.runtime.AppEngineConstants.WARMUP_REQUEST_URL; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_API_TICKET; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_DATACENTER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_TASK_BNS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_AUTH_DOMAIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_BACKGROUNDREQUEST; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_DEFAULT_VERSION_HOSTNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_AUTHUSER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_SESSION; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_HTTPS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_ID_HASH; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_LOAS_PEER_USERNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_QUEUENAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_REQUEST_LOG_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TIMEOUT_MS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TRUSTED_IP_REQUEST; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_EMAIL; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IP; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IS_ADMIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ORGANIZATION; +import static com.google.apphosting.runtime.AppEngineConstants.X_CLOUD_TRACE_CONTEXT; +import static com.google.apphosting.runtime.AppEngineConstants.X_FORWARDED_PROTO; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_PROFILER; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK; + +import com.google.apphosting.base.protos.HttpPb; +import com.google.apphosting.base.protos.RuntimePb; +import com.google.apphosting.base.protos.TracePb; +import com.google.apphosting.runtime.AppEngineConstants; +import com.google.apphosting.runtime.RequestAPIData; +import com.google.apphosting.runtime.TraceContextHelper; +import com.google.common.base.Strings; +import com.google.common.flogger.GoogleLogger; +import java.time.Duration; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; + +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpScheme; +import org.eclipse.jetty.http.HttpURI; +import org.eclipse.jetty.server.Request; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +/** + * Implementation for the {@link RequestAPIData} to allow for the Jetty {@link Request} to be used + * directly with the Java Runtime without any conversion into the RPC {@link RuntimePb.UPRequest}. + * + *

This will interpret the AppEngine specific headers defined in {@link AppEngineConstants}. The + * request returned by {@link #getBaseRequest()} is to be passed to the application and will hide + * any private appengine headers from {@link AppEngineConstants#PRIVATE_APPENGINE_HEADERS}. + */ +public class JettyRequestAPIData implements RequestAPIData { + private static final GoogleLogger logger = GoogleLogger.forEnclosingClass(); + + private final Request baseRequest; + private final HttpServletRequest httpServletRequest; + private final AppInfoFactory appInfoFactory; + private final String url; + private Duration duration = Duration.ofNanos(Long.MAX_VALUE); + private RuntimePb.UPRequest.RequestType requestType = OTHER; + private String authDomain = ""; + private boolean isTrusted; + private boolean isTrustedApp; + private boolean isAdmin; + private boolean isHttps; + private boolean isOffline; + private TracePb.TraceContextProto traceContext; + private String obfuscatedGaiaId; + private String userOrganization = ""; + private String peerUsername; + private long gaiaId; + private String authUser; + private String gaiaSession; + private String appserverDataCenter; + String appserverTaskBns; + String eventIdHash; + private String requestLogId; + private String defaultVersionHostname; + private String email = ""; + private String securityTicket; + private String backgroundRequestId; + + public JettyRequestAPIData(Request request, HttpServletRequest httpServletRequest, + AppInfoFactory appInfoFactory, boolean passThroughPrivateHeaders) { + this.appInfoFactory = appInfoFactory; + + // Can be overridden by X_APPENGINE_USER_IP header. + String userIp = request.getRemoteAddr(); + + // Can be overridden by X_APPENGINE_API_TICKET header. + this.securityTicket = DEFAULT_SECRET_KEY; + + HttpFields fields = new HttpFields(); + List headerNames = Collections.list(request.getHeaderNames()); + for (String headerName : headerNames) { + String name = headerName.toLowerCase(); + String value = request.getHeader(headerName); + if (Strings.isNullOrEmpty(value)) { + continue; + } + + switch (name) { + case X_APPENGINE_TRUSTED_IP_REQUEST: + // If there is a value, then the application is trusted + // If the value is IS_TRUSTED, then the user is trusted + isTrusted = value.equals(IS_TRUSTED); + isTrustedApp = true; + break; + case X_APPENGINE_HTTPS: + isHttps = value.equals("on"); + break; + case X_APPENGINE_USER_IP: + userIp = value; + break; + case X_FORWARDED_PROTO: + isHttps = value.equals("https"); + break; + case X_APPENGINE_USER_ID: + obfuscatedGaiaId = value; + break; + case X_APPENGINE_USER_ORGANIZATION: + userOrganization = value; + break; + case X_APPENGINE_LOAS_PEER_USERNAME: + peerUsername = value; + break; + case X_APPENGINE_GAIA_ID: + gaiaId = Long.parseLong(value); + break; + case X_APPENGINE_GAIA_AUTHUSER: + authUser = value; + break; + case X_APPENGINE_GAIA_SESSION: + gaiaSession = value; + break; + case X_APPENGINE_APPSERVER_DATACENTER: + appserverDataCenter = value; + break; + case X_APPENGINE_APPSERVER_TASK_BNS: + appserverTaskBns = value; + break; + case X_APPENGINE_ID_HASH: + eventIdHash = value; + break; + case X_APPENGINE_REQUEST_LOG_ID: + requestLogId = value; + break; + case X_APPENGINE_DEFAULT_VERSION_HOSTNAME: + defaultVersionHostname = value; + break; + case X_APPENGINE_USER_IS_ADMIN: + isAdmin = Objects.equals(value, IS_ADMIN_HEADER_VALUE); + break; + case X_APPENGINE_USER_EMAIL: + email = value; + break; + case X_APPENGINE_AUTH_DOMAIN: + authDomain = value; + break; + case X_APPENGINE_API_TICKET: + securityTicket = value; + break; + + case X_CLOUD_TRACE_CONTEXT: + try { + traceContext = TraceContextHelper.parseTraceContextHeader(value); + } catch (NumberFormatException e) { + logger.atWarning().withCause(e).log("Could not parse trace context header: %s", value); + } + break; + + case X_GOOGLE_INTERNAL_SKIPADMINCHECK: + request.setAttribute(SKIP_ADMIN_CHECK_ATTR, true); + isHttps = true; + break; + + case X_APPENGINE_QUEUENAME: + request.setAttribute(SKIP_ADMIN_CHECK_ATTR, true); + isOffline = true; + break; + + case X_APPENGINE_TIMEOUT_MS: + duration = Duration.ofMillis(Long.parseLong(value)); + break; + + case X_GOOGLE_INTERNAL_PROFILER: + /* TODO: what to do here? + try { + TextFormat.merge(value, upReqBuilder.getProfilerSettingsBuilder()); + } catch (IOException ex) { + throw new IllegalStateException("X-Google-Internal-Profiler read content error:", ex); + } + */ + break; + + case X_APPENGINE_BACKGROUNDREQUEST: + backgroundRequestId = value; + break; + + default: + break; + } + + if (passThroughPrivateHeaders || !PRIVATE_APPENGINE_HEADERS.contains(name)) { + // Only non AppEngine specific headers are passed to the application. + fields.add(name, value); + } + } + + HttpURI httpURI; + boolean isSecure; + if (isHttps) { + httpURI = new HttpURI(request.getHttpURI()); + httpURI.setScheme(HttpScheme.HTTPS.asString()); + isSecure = true; + } else { + httpURI = request.getHttpURI(); + isSecure = request.isSecure(); + } + + String decodedPath = request.getHttpURI().getDecodedPath(); + if (BACKGROUND_REQUEST_URL.equals(decodedPath)) { + if (WARMUP_IP.equals(userIp)) { + requestType = RuntimePb.UPRequest.RequestType.BACKGROUND; + } + } else if (WARMUP_REQUEST_URL.equals(decodedPath)) { + if (WARMUP_IP.equals(userIp)) { + // This request came from within App Engine via secure internal channels; tell Jetty + // it's HTTPS to avoid 403 because of web.xml security-constraint checks. + isHttps = true; + } + } + + HttpURI uri = new HttpURI(httpURI); + uri.setQuery(null); + StringBuilder sb = new StringBuilder(uri.toString()); + String query = httpURI.getQuery(); + // No need to escape, URL retains any %-escaping it might have, which is what we want. + if (query != null) { + sb.append('?').append(query); + } + url = sb.toString(); + + if (traceContext == null) { + traceContext = + com.google.apphosting.base.protos.TracePb.TraceContextProto.getDefaultInstance(); + } + + this.httpServletRequest = new HttpServletRequestWrapper(httpServletRequest) { + + @Override + public long getDateHeader(String name) { + return fields.getDateField(name); + } + + @Override + public String getHeader(String name) { + return fields.get(name); + } + + @Override + public Enumeration getHeaders(String name) { + return fields.getValues(name); + } + + @Override + public Enumeration getHeaderNames() { + return fields.getFieldNames(); + } + + @Override + public int getIntHeader(String name) { + return Math.toIntExact(fields.getLongField(name)); + } + + @Override + public String getRequestURI() { + return httpURI.getPath(); + } + + @Override + public String getScheme() { + return httpURI.getScheme(); + } + + @Override + public boolean isSecure() { + return isSecure; + } + }; + + this.baseRequest = request; + } + + public Request getBaseRequest() { + return baseRequest; + } + + public HttpServletRequest getHttpServletRequest() { + return httpServletRequest; + } + + @Override + public Stream getHeadersList() { + return baseRequest.getHttpFields().stream() + .map( + f -> + HttpPb.ParsedHttpHeader.newBuilder() + .setKey(f.getName()) + .setValue(f.getValue()) + .build()); + } + + @Override + public String getUrl() { + return url; + } + + @Override + public RuntimePb.UPRequest.RequestType getRequestType() { + return requestType; + } + + @Override + public String getBackgroundRequestId() { + return backgroundRequestId; + } + + @Override + public boolean hasTraceContext() { + return traceContext != null; + } + + @Override + public TracePb.TraceContextProto getTraceContext() { + return traceContext; + } + + @Override + public String getSecurityLevel() { + // TODO(b/78515194) Need to find a mapping for this field. + return null; + } + + @Override + public boolean getIsOffline() { + return isOffline; + } + + @Override + public String getAppId() { + return appInfoFactory.getGaeApplication(); + } + + @Override + public String getModuleId() { + return appInfoFactory.getGaeService(); + } + + @Override + public String getModuleVersionId() { + return appInfoFactory.getGaeServiceVersion(); + } + + @Override + public String getObfuscatedGaiaId() { + return obfuscatedGaiaId; + } + + @Override + public String getUserOrganization() { + return userOrganization; + } + + @Override + public boolean getIsTrustedApp() { + return isTrustedApp; + } + + @Override + public boolean getTrusted() { + return isTrusted; + } + + @Override + public String getPeerUsername() { + return peerUsername; + } + + @Override + public long getGaiaId() { + return gaiaId; + } + + @Override + public String getAuthuser() { + return authUser; + } + + @Override + public String getGaiaSession() { + return gaiaSession; + } + + @Override + public String getAppserverDatacenter() { + return appserverDataCenter; + } + + @Override + public String getAppserverTaskBns() { + return appserverTaskBns; + } + + @Override + public boolean hasEventIdHash() { + return eventIdHash != null; + } + + @Override + public String getEventIdHash() { + return eventIdHash; + } + + @Override + public boolean hasRequestLogId() { + return requestLogId != null; + } + + @Override + public String getRequestLogId() { + return requestLogId; + } + + @Override + public boolean hasDefaultVersionHostname() { + return defaultVersionHostname != null; + } + + @Override + public String getDefaultVersionHostname() { + return defaultVersionHostname; + } + + @Override + public boolean getIsAdmin() { + return isAdmin; + } + + @Override + public String getEmail() { + return email; + } + + @Override + public String getAuthDomain() { + return authDomain; + } + + @Override + public String getSecurityTicket() { + return securityTicket; + } + + public Duration getTimeRemaining() { + return duration; + } +} diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyResponseAPIData.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyResponseAPIData.java new file mode 100644 index 000000000..479d36d79 --- /dev/null +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyResponseAPIData.java @@ -0,0 +1,90 @@ +/* + * Copyright 2021 Google LLC + * + * 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 + * + * https://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.apphosting.runtime.jetty9; + +import com.google.apphosting.base.protos.AppLogsPb; +import com.google.apphosting.base.protos.RuntimePb; +import com.google.apphosting.runtime.ResponseAPIData; +import com.google.apphosting.runtime.anyrpc.AnyRpcServerContext; +import com.google.protobuf.ByteString; +import org.eclipse.jetty.server.Response; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import javax.servlet.http.HttpServletResponse; + +public class JettyResponseAPIData implements ResponseAPIData { + + private final Response response; + private final HttpServletResponse httpServletResponse; + + public JettyResponseAPIData(Response response, HttpServletResponse httpServletResponse) { + this.response = response; + this.httpServletResponse = httpServletResponse; + } + + public Response getResponse() { + return response; + } + + public HttpServletResponse getHttpServletResponse() { + return httpServletResponse; + } + + @Override + public void addAppLog(AppLogsPb.AppLogLine logLine) {} + + @Override + public int getAppLogCount() { + return 0; + } + + @Override + public List getAndClearAppLogList() { + return Collections.emptyList(); + } + + @Override + public void setSerializedTrace(ByteString byteString) {} + + @Override + public void setTerminateClone(boolean terminateClone) {} + + @Override + public void setCloneIsInUncleanState(boolean b) {} + + @Override + public void setUserMcycles(long l) {} + + @Override + public void addAllRuntimeLogLine(Collection logLines) {} + + @Override + public void error(int error, String errorMessage) {} + + @Override + public void finishWithResponse(AnyRpcServerContext rpc) {} + + @Override + public void complete() {} + + @Override + public int getError() { + return 0; + } +} diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/LocalRpcContext.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/LocalRpcContext.java new file mode 100644 index 000000000..4de3bc6fc --- /dev/null +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/LocalRpcContext.java @@ -0,0 +1,75 @@ +/* + * Copyright 2021 Google LLC + * + * 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 + * + * https://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.apphosting.runtime.jetty9; + +import com.google.apphosting.runtime.anyrpc.AnyRpcServerContext; +import com.google.common.util.concurrent.SettableFuture; +import com.google.protobuf.MessageLite; +import java.time.Duration; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicLong; + +public class LocalRpcContext implements AnyRpcServerContext { + // We just dole out sequential ids here so we can tell requests apart in the logs. + private static final AtomicLong globalIds = new AtomicLong(); + + private final Class responseMessageClass; + private final long startTimeMillis; + private final Duration timeRemaining; + private final SettableFuture futureResponse = SettableFuture.create(); + private final long globalId = globalIds.getAndIncrement(); + + public LocalRpcContext(Class responseMessageClass) { + this(responseMessageClass, Duration.ofNanos((long) Double.MAX_VALUE)); + } + + public LocalRpcContext(Class responseMessageClass, Duration timeRemaining) { + this.responseMessageClass = responseMessageClass; + this.startTimeMillis = System.currentTimeMillis(); + this.timeRemaining = timeRemaining; + } + + @Override + public void finishWithResponse(MessageLite response) { + futureResponse.set(responseMessageClass.cast(response)); + } + + public M getResponse() throws ExecutionException, InterruptedException { + return futureResponse.get(); + } + + @Override + public void finishWithAppError(int appErrorCode, String errorDetail) { + String message = "AppError: code " + appErrorCode + "; errorDetail " + errorDetail; + futureResponse.setException(new RuntimeException(message)); + } + + @Override + public Duration getTimeRemaining() { + return timeRemaining; + } + + @Override + public long getGlobalId() { + return globalId; + } + + @Override + public long getStartTimeMillis() { + return startTimeMillis; + } +} diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/ResourceFileServlet.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/ResourceFileServlet.java index 68bddac18..6cea7c23e 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/ResourceFileServlet.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/ResourceFileServlet.java @@ -17,7 +17,7 @@ package com.google.apphosting.runtime.jetty9; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.utils.config.AppYaml; import com.google.common.base.Ascii; import com.google.common.flogger.GoogleLogger; @@ -68,11 +68,11 @@ public class ResourceFileServlet extends HttpServlet { public void init() throws ServletException { context = getServletContext(); AppVersion appVersion = - (AppVersion) context.getAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR); + (AppVersion) context.getAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR); chandler = ((ContextHandler.Context) context).getContextHandler(); AppYaml appYaml = - (AppYaml) chandler.getServer().getAttribute(JettyConstants.APP_YAML_ATTRIBUTE_TARGET); + (AppYaml) chandler.getServer().getAttribute(AppEngineConstants.APP_YAML_ATTRIBUTE_TARGET); fSender = new FileSender(appYaml); // AFAICT, there is no real API to retrieve this information, so // we access Jetty's internal state. @@ -250,7 +250,7 @@ private boolean maybeServeWelcomeFile( } AppVersion appVersion = - (AppVersion) getServletContext().getAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR); + (AppVersion) getServletContext().getAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR); ServletHandler handler = chandler.getChildHandlerByClass(ServletHandler.class); MappedResource defaultEntry = handler.getHolderEntry("/"); diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/RpcConnection.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/RpcConnection.java index ad5c18ac6..e69f7797d 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/RpcConnection.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/RpcConnection.java @@ -21,7 +21,7 @@ import com.google.apphosting.base.protos.HttpPb.ParsedHttpHeader; import com.google.apphosting.base.protos.RuntimePb.UPRequest; import com.google.apphosting.base.protos.RuntimePb.UPResponse; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.MutableUpResponse; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Ascii; @@ -245,7 +245,7 @@ public void onCompleted() { // Tell AppVersionHandlerMap which app version should handle this // request. - request.setAttribute(JettyConstants.APP_VERSION_KEY_REQUEST_ATTR, appVersionKey); + request.setAttribute(AppEngineConstants.APP_VERSION_KEY_REQUEST_ATTR, appVersionKey); final boolean skipAdmin = hasSkipAdminCheck(endPoint.getUpRequest()); // Translate the X-Google-Internal-SkipAdminCheck to a servlet attribute. diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/UPRequestTranslator.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/UPRequestTranslator.java index 4cdef9797..bf697635e 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/UPRequestTranslator.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/UPRequestTranslator.java @@ -16,6 +16,37 @@ package com.google.apphosting.runtime.jetty9; +import static com.google.apphosting.runtime.AppEngineConstants.BACKGROUND_REQUEST_URL; +import static com.google.apphosting.runtime.AppEngineConstants.DEFAULT_SECRET_KEY; +import static com.google.apphosting.runtime.AppEngineConstants.IS_ADMIN_HEADER_VALUE; +import static com.google.apphosting.runtime.AppEngineConstants.IS_TRUSTED; +import static com.google.apphosting.runtime.AppEngineConstants.PRIVATE_APPENGINE_HEADERS; +import static com.google.apphosting.runtime.AppEngineConstants.WARMUP_IP; +import static com.google.apphosting.runtime.AppEngineConstants.WARMUP_REQUEST_URL; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_API_TICKET; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_DATACENTER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_TASK_BNS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_AUTH_DOMAIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_DEFAULT_VERSION_HOSTNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_AUTHUSER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_SESSION; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_HTTPS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_LOAS_PEER_USERNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_QUEUENAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_REQUEST_LOG_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TIMEOUT_MS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TRUSTED_IP_REQUEST; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_EMAIL; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IP; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IS_ADMIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ORGANIZATION; +import static com.google.apphosting.runtime.AppEngineConstants.X_CLOUD_TRACE_CONTEXT; +import static com.google.apphosting.runtime.AppEngineConstants.X_FORWARDED_PROTO; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_PROFILER; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK; + import com.google.apphosting.base.protos.AppinfoPb; import com.google.apphosting.base.protos.HttpPb; import com.google.apphosting.base.protos.HttpPb.HttpRequest; @@ -26,7 +57,6 @@ import com.google.apphosting.runtime.TraceContextHelper; import com.google.common.base.Ascii; import com.google.common.base.Strings; -import com.google.common.collect.ImmutableSet; import com.google.common.flogger.GoogleLogger; import com.google.common.html.HtmlEscapers; import com.google.protobuf.ByteString; @@ -39,6 +69,9 @@ import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK_UC; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_NICKNAME; + /** Translates HttpServletRequest to the UPRequest proto, and vice versa for the response. */ public class UPRequestTranslator { @@ -46,69 +79,7 @@ public class UPRequestTranslator { private static final String DEFAULT_SECRET_KEY = "secretkey"; - /** - * The HTTP headers that are handled specially by this proxy are defined in lowercae because HTTP - * headers are case insensitive and we look then up in a set or switch after converting to - * lower-case. - */ - private static final String X_FORWARDED_PROTO = "x-forwarded-proto"; - - private static final String X_APPENGINE_API_TICKET = "x-appengine-api-ticket"; - private static final String X_APPENGINE_HTTPS = "x-appengine-https"; - private static final String X_APPENGINE_USER_IP = "x-appengine-user-ip"; - private static final String X_APPENGINE_USER_EMAIL = "x-appengine-user-email"; - private static final String X_APPENGINE_AUTH_DOMAIN = "x-appengine-auth-domain"; - private static final String X_APPENGINE_USER_ID = "x-appengine-user-id"; - private static final String X_APPENGINE_USER_NICKNAME = "x-appengine-user-nickname"; - private static final String X_APPENGINE_USER_ORGANIZATION = "x-appengine-user-organization"; - private static final String X_APPENGINE_USER_IS_ADMIN = "x-appengine-user-is-admin"; - private static final String X_APPENGINE_TRUSTED_IP_REQUEST = "x-appengine-trusted-ip-request"; - private static final String X_APPENGINE_LOAS_PEER_USERNAME = "x-appengine-loas-peer-username"; - private static final String X_APPENGINE_GAIA_ID = "x-appengine-gaia-id"; - private static final String X_APPENGINE_GAIA_AUTHUSER = "x-appengine-gaia-authuser"; - private static final String X_APPENGINE_GAIA_SESSION = "x-appengine-gaia-session"; - private static final String X_APPENGINE_APPSERVER_DATACENTER = "x-appengine-appserver-datacenter"; - private static final String X_APPENGINE_APPSERVER_TASK_BNS = "x-appengine-appserver-task-bns"; - private static final String X_APPENGINE_DEFAULT_VERSION_HOSTNAME = - "x-appengine-default-version-hostname"; - private static final String X_APPENGINE_REQUEST_LOG_ID = "x-appengine-request-log-id"; - private static final String X_APPENGINE_QUEUENAME = "x-appengine-queuename"; - private static final String X_APPENGINE_TIMEOUT_MS = "x-appengine-timeout-ms"; - private static final String X_GOOGLE_INTERNAL_SKIPADMINCHECK = "x-google-internal-skipadmincheck"; - private static final String X_GOOGLE_INTERNAL_SKIPADMINCHECK_UC = - "X-Google-Internal-SkipAdminCheck"; - private static final String X_GOOGLE_INTERNAL_PROFILER = "x-google-internal-profiler"; - private static final String X_CLOUD_TRACE_CONTEXT = "x-cloud-trace-context"; - - private static final String IS_ADMIN_HEADER_VALUE = "1"; - private static final String IS_TRUSTED = "1"; - - // The impersonated IP address of warmup requests (and also background) - // () - private static final String WARMUP_IP = "0.1.0.3"; - - private static final ImmutableSet PRIVATE_APPENGINE_HEADERS = - ImmutableSet.of( - X_APPENGINE_API_TICKET, - X_APPENGINE_HTTPS, - X_APPENGINE_USER_IP, - X_APPENGINE_USER_EMAIL, - X_APPENGINE_AUTH_DOMAIN, - X_APPENGINE_USER_ID, - X_APPENGINE_USER_NICKNAME, - X_APPENGINE_USER_ORGANIZATION, - X_APPENGINE_USER_IS_ADMIN, - X_APPENGINE_TRUSTED_IP_REQUEST, - X_APPENGINE_LOAS_PEER_USERNAME, - X_APPENGINE_GAIA_ID, - X_APPENGINE_GAIA_AUTHUSER, - X_APPENGINE_GAIA_SESSION, - X_APPENGINE_APPSERVER_DATACENTER, - X_APPENGINE_APPSERVER_TASK_BNS, - X_APPENGINE_DEFAULT_VERSION_HOSTNAME, - X_APPENGINE_REQUEST_LOG_ID, - X_APPENGINE_TIMEOUT_MS, - X_GOOGLE_INTERNAL_PROFILER); + private final AppInfoFactory appInfoFactory; private final boolean passThroughPrivateHeaders; @@ -230,11 +201,11 @@ public final RuntimePb.UPRequest translateRequest(HttpServletRequest realRequest } } - if ("/_ah/background".equals(realRequest.getRequestURI())) { + if (BACKGROUND_REQUEST_URL.equals(realRequest.getRequestURI())) { if (WARMUP_IP.equals(httpRequest.getUserIp())) { upReqBuilder.setRequestType(UPRequest.RequestType.BACKGROUND); } - } else if ("/_ah/start".equals(realRequest.getRequestURI())) { + } else if (WARMUP_REQUEST_URL.equals(realRequest.getRequestURI())) { if (WARMUP_IP.equals(httpRequest.getUserIp())) { // This request came from within App Engine via secure internal channels; tell Jetty // it's HTTPS to avoid 403 because of web.xml security-constraint checks. From ff0818b875d53e664ad15278226b7fcaef53a261 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Wed, 26 Jun 2024 16:48:53 +1000 Subject: [PATCH 13/28] move LocalRpcContext to runtime-impl Signed-off-by: Lachlan Roberts --- .../apphosting/runtime}/LocalRpcContext.java | 2 +- .../jetty/JettyServletEngineAdapter.java | 3 +- .../runtime/jetty/http/JettyHttpHandler.java | 5 +- .../runtime/jetty/http/LocalRpcContext.java | 75 ------------------- .../runtime/jetty/proxy/JettyHttpProxy.java | 2 +- .../runtime/jetty9/JettyHttpHandler.java | 1 + 6 files changed, 5 insertions(+), 83 deletions(-) rename runtime/{runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9 => impl/src/main/java/com/google/apphosting/runtime}/LocalRpcContext.java (98%) delete mode 100644 runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/LocalRpcContext.java diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/LocalRpcContext.java b/runtime/impl/src/main/java/com/google/apphosting/runtime/LocalRpcContext.java similarity index 98% rename from runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/LocalRpcContext.java rename to runtime/impl/src/main/java/com/google/apphosting/runtime/LocalRpcContext.java index 4de3bc6fc..0f65a63d2 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/LocalRpcContext.java +++ b/runtime/impl/src/main/java/com/google/apphosting/runtime/LocalRpcContext.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.google.apphosting.runtime.jetty9; +package com.google.apphosting.runtime; import com.google.apphosting.runtime.anyrpc.AnyRpcServerContext; import com.google.common.util.concurrent.SettableFuture; diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java index 20557d100..4c93bf5b9 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java @@ -23,14 +23,13 @@ import com.google.apphosting.base.protos.RuntimePb.UPResponse; import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.AppEngineConstants; +import com.google.apphosting.runtime.LocalRpcContext; import com.google.apphosting.runtime.MutableUpResponse; import com.google.apphosting.runtime.ServletEngineAdapter; import com.google.apphosting.runtime.anyrpc.EvaluationRuntimeServerInterface; import com.google.apphosting.runtime.jetty.delegate.DelegateConnector; import com.google.apphosting.runtime.jetty.delegate.impl.DelegateRpcExchange; import com.google.apphosting.runtime.jetty.http.JettyHttpHandler; -import com.google.apphosting.runtime.jetty.http.LocalRpcContext; import com.google.apphosting.runtime.jetty.proxy.JettyHttpProxy; import com.google.apphosting.utils.config.AppEngineConfigException; import com.google.apphosting.utils.config.AppYaml; diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyHttpHandler.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyHttpHandler.java index f188f0d0e..dabc62587 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyHttpHandler.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyHttpHandler.java @@ -25,16 +25,14 @@ import com.google.apphosting.runtime.AppVersion; import com.google.apphosting.runtime.BackgroundRequestCoordinator; import com.google.apphosting.runtime.AppEngineConstants; +import com.google.apphosting.runtime.LocalRpcContext; import com.google.apphosting.runtime.RequestManager; import com.google.apphosting.runtime.RequestRunner; import com.google.apphosting.runtime.RequestRunner.EagerRunner; import com.google.apphosting.runtime.ResponseAPIData; import com.google.apphosting.runtime.ServletEngineAdapter; -import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.jetty.AppInfoFactory; -import com.google.common.base.Ascii; import com.google.common.flogger.GoogleLogger; -import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; @@ -45,7 +43,6 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.time.Duration; -import java.util.Optional; import java.util.concurrent.TimeoutException; import static com.google.apphosting.runtime.RequestRunner.WAIT_FOR_USER_RUNNABLE_DEADLINE; diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/LocalRpcContext.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/LocalRpcContext.java deleted file mode 100644 index 163f80f58..000000000 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/LocalRpcContext.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * 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 - * - * https://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.apphosting.runtime.jetty.http; - -import com.google.apphosting.runtime.anyrpc.AnyRpcServerContext; -import com.google.common.util.concurrent.SettableFuture; -import com.google.protobuf.MessageLite; -import java.time.Duration; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicLong; - -public class LocalRpcContext implements AnyRpcServerContext { - // We just dole out sequential ids here so we can tell requests apart in the logs. - private static final AtomicLong globalIds = new AtomicLong(); - - private final Class responseMessageClass; - private final long startTimeMillis; - private final Duration timeRemaining; - private final SettableFuture futureResponse = SettableFuture.create(); - private final long globalId = globalIds.getAndIncrement(); - - public LocalRpcContext(Class responseMessageClass) { - this(responseMessageClass, Duration.ofNanos((long) Double.MAX_VALUE)); - } - - public LocalRpcContext(Class responseMessageClass, Duration timeRemaining) { - this.responseMessageClass = responseMessageClass; - this.startTimeMillis = System.currentTimeMillis(); - this.timeRemaining = timeRemaining; - } - - @Override - public void finishWithResponse(MessageLite response) { - futureResponse.set(responseMessageClass.cast(response)); - } - - public M getResponse() throws ExecutionException, InterruptedException { - return futureResponse.get(); - } - - @Override - public void finishWithAppError(int appErrorCode, String errorDetail) { - String message = "AppError: code " + appErrorCode + "; errorDetail " + errorDetail; - futureResponse.setException(new RuntimeException(message)); - } - - @Override - public Duration getTimeRemaining() { - return timeRemaining; - } - - @Override - public long getGlobalId() { - return globalId; - } - - @Override - public long getStartTimeMillis() { - return startTimeMillis; - } -} diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/JettyHttpProxy.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/JettyHttpProxy.java index f4fc800a1..e65db0438 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/JettyHttpProxy.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/JettyHttpProxy.java @@ -20,12 +20,12 @@ import com.google.apphosting.base.protos.RuntimePb; import com.google.apphosting.base.protos.RuntimePb.UPRequest; import com.google.apphosting.base.protos.RuntimePb.UPResponse; +import com.google.apphosting.runtime.LocalRpcContext; import com.google.apphosting.runtime.ServletEngineAdapter; import com.google.apphosting.runtime.anyrpc.EvaluationRuntimeServerInterface; import com.google.apphosting.runtime.jetty.AppInfoFactory; import com.google.apphosting.runtime.jetty.CoreSizeLimitHandler; import com.google.apphosting.runtime.jetty.JettyServletEngineAdapter; -import com.google.apphosting.runtime.jetty.http.LocalRpcContext; import com.google.common.base.Ascii; import com.google.common.base.Throwables; import com.google.common.flogger.GoogleLogger; diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpHandler.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpHandler.java index 98e52235c..6b3d75f49 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpHandler.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpHandler.java @@ -27,6 +27,7 @@ import com.google.apphosting.runtime.AppVersion; import com.google.apphosting.runtime.BackgroundRequestCoordinator; import com.google.apphosting.runtime.AppEngineConstants; +import com.google.apphosting.runtime.LocalRpcContext; import com.google.apphosting.runtime.RequestManager; import com.google.apphosting.runtime.RequestRunner; import com.google.apphosting.runtime.RequestRunner.EagerRunner; From 2ff5834d6156038b4a5908ff55a615d47b0d6908 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Wed, 26 Jun 2024 16:51:40 +1000 Subject: [PATCH 14/28] move LocalRpcContext to runtime-impl Signed-off-by: Lachlan Roberts --- .../runtime/jetty9/JettyHttpProxy.java | 56 +------------------ 1 file changed, 1 insertion(+), 55 deletions(-) diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpProxy.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpProxy.java index b25b5048d..bc304e4c6 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpProxy.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpProxy.java @@ -22,20 +22,17 @@ import com.google.apphosting.base.protos.RuntimePb; import com.google.apphosting.base.protos.RuntimePb.UPRequest; import com.google.apphosting.base.protos.RuntimePb.UPResponse; +import com.google.apphosting.runtime.LocalRpcContext; import com.google.apphosting.runtime.ServletEngineAdapter; -import com.google.apphosting.runtime.anyrpc.AnyRpcServerContext; import com.google.apphosting.runtime.anyrpc.EvaluationRuntimeServerInterface; import com.google.common.base.Ascii; import com.google.common.base.Throwables; import com.google.common.flogger.GoogleLogger; import com.google.common.primitives.Ints; -import com.google.common.util.concurrent.SettableFuture; -import com.google.protobuf.MessageLite; import java.io.IOException; import java.time.Duration; import java.util.Map; import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicLong; import java.util.logging.Level; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -129,57 +126,6 @@ public static Server newServer( return server; } - private static class LocalRpcContext implements AnyRpcServerContext { - // We just dole out sequential ids here so we can tell requests apart in the logs. - private static final AtomicLong globalIds = new AtomicLong(); - - private final Class responseMessageClass; - private final long startTimeMillis; - private final Duration timeRemaining; - private final SettableFuture futureResponse = SettableFuture.create(); - private final long globalId = globalIds.getAndIncrement(); - - private LocalRpcContext(Class responseMessageClass) { - this(responseMessageClass, Duration.ofNanos((long) Double.MAX_VALUE)); - } - - private LocalRpcContext(Class responseMessageClass, Duration timeRemaining) { - this.responseMessageClass = responseMessageClass; - this.startTimeMillis = System.currentTimeMillis(); - this.timeRemaining = timeRemaining; - } - - @Override - public void finishWithResponse(MessageLite response) { - futureResponse.set(responseMessageClass.cast(response)); - } - - M getResponse() throws ExecutionException, InterruptedException { - return futureResponse.get(); - } - - @Override - public void finishWithAppError(int appErrorCode, String errorDetail) { - String message = "AppError: code " + appErrorCode + "; errorDetail " + errorDetail; - futureResponse.setException(new RuntimeException(message)); - } - - @Override - public Duration getTimeRemaining() { - return timeRemaining; - } - - @Override - public long getGlobalId() { - return globalId; - } - - @Override - public long getStartTimeMillis() { - return startTimeMillis; - } - } - /** * Handler to stub out the frontend server. This has to launch the runtime, configure the user's * app into it, and then forward HTTP requests over gRPC to the runtime and decode the responses. From a7ad919a8462ad7482a5f4c39ba93557f13c49de Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Thu, 27 Jun 2024 14:40:00 +1000 Subject: [PATCH 15/28] Add HttpConnector mode for Jetty9.4 runtimes Signed-off-by: Lachlan Roberts --- .../jetty9/AppVersionHandlerFactory.java | 16 ----- .../runtime/jetty9/AppVersionHandlerMap.java | 22 ++----- .../runtime/jetty9/JettyHttpHandler.java | 5 +- .../runtime/jetty9/JettyHttpProxy.java | 66 ++++++++----------- .../jetty9/JettyServletEngineAdapter.java | 53 +++++++++++++-- 5 files changed, 83 insertions(+), 79 deletions(-) diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerFactory.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerFactory.java index cf4696847..d28cd8c1c 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerFactory.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerFactory.java @@ -230,23 +230,7 @@ public void exitScope( }); } - context.start(); - // Check to see if servlet filter initialization failed. - Throwable unavailableCause = context.getUnavailableException(); - if (unavailableCause != null) { - if (unavailableCause instanceof ServletException) { - throw (ServletException) unavailableCause; - } else { - UnavailableException unavailableException = - new UnavailableException("Initialization failed."); - unavailableException.initCause(unavailableCause); - throw unavailableException; - } - } - return context; - } catch (ServletException ex) { - throw ex; } catch (Exception ex) { throw new ServletException(ex); } diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerMap.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerMap.java index 5d63b6a6d..22c00ac4e 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerMap.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerMap.java @@ -95,6 +95,10 @@ public synchronized Handler getHandler(AppVersionKey appVersionKey) throws Servl return handler; } + public AppVersion getAppVersion(AppVersionKey appVersionKey) { + return appVersionMap.get(appVersionKey); + } + /** * Forward the specified request on to the {@link Handler} associated with its application * version. @@ -127,24 +131,6 @@ public void handle( } } - @Override - protected void doStart() throws Exception { - for (Handler handler : getHandlers()) { - handler.start(); - } - - super.doStart(); - } - - @Override - protected void doStop() throws Exception { - super.doStop(); - - for (Handler handler : getHandlers()) { - handler.stop(); - } - } - @Override public void setServer(Server server) { super.setServer(server); diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpHandler.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpHandler.java index 6b3d75f49..e482fe8c3 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpHandler.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpHandler.java @@ -138,7 +138,7 @@ public void handle( } } - private boolean dispatchRequest( + private void dispatchRequest( String target, RequestManager.RequestToken requestToken, JettyRequestAPIData request, @@ -149,11 +149,14 @@ private boolean dispatchRequest( logger.atInfo().log("Shutting down requests"); requestManager.shutdownRequests(requestToken); request.getBaseRequest().setHandled(true); + break; case BACKGROUND: dispatchBackgroundRequest(request, response); request.getBaseRequest().setHandled(true); + break; case OTHER: dispatchServletRequest(target, request, response); + break; default: throw new IllegalStateException(request.getRequestType().toString()); } diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpProxy.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpProxy.java index bc304e4c6..e773a0230 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpProxy.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyHttpProxy.java @@ -36,6 +36,8 @@ import java.util.logging.Level; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.http.CookieCompliance; import org.eclipse.jetty.http.HttpCompliance; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpConfiguration; @@ -80,7 +82,6 @@ public static void startServer(ServletEngineAdapter.Config runtimeOptions) { System.setProperty(JETTY_LOG_CLASS, JETTY_STDERRLOG); ForwardingHandler handler = new ForwardingHandler(runtimeOptions, System.getenv()); - handler.init(); Server server = newServer(runtimeOptions, handler); server.start(); } catch (Exception ex) { @@ -88,19 +89,15 @@ public static void startServer(ServletEngineAdapter.Config runtimeOptions) { } } - public static Server newServer( - ServletEngineAdapter.Config runtimeOptions, ForwardingHandler handler) { - Server server = new Server(); - - ServerConnector c = - new JettyServerConnectorWithReusePort(server, runtimeOptions.jettyReusePort()); - c.setHost(runtimeOptions.jettyHttpAddress().getHost()); - c.setPort(runtimeOptions.jettyHttpAddress().getPort()); - server.setConnectors(new Connector[] {c}); + public static ServerConnector newConnector(Server server, ServletEngineAdapter.Config runtimeOptions) { + ServerConnector connector = + new JettyServerConnectorWithReusePort(server, runtimeOptions.jettyReusePort()); + connector.setHost(runtimeOptions.jettyHttpAddress().getHost()); + connector.setPort(runtimeOptions.jettyHttpAddress().getPort()); - HttpConnectionFactory factory = c.getConnectionFactory(HttpConnectionFactory.class); + HttpConnectionFactory factory = connector.getConnectionFactory(HttpConnectionFactory.class); factory.setHttpCompliance( - RpcConnector.LEGACY_MODE ? HttpCompliance.RFC7230_LEGACY : HttpCompliance.RFC7230); + RpcConnector.LEGACY_MODE ? HttpCompliance.RFC7230_LEGACY : HttpCompliance.RFC7230); HttpConfiguration config = factory.getHttpConfiguration(); config.setRequestHeaderSize(runtimeOptions.jettyRequestHeaderSize()); @@ -109,18 +106,29 @@ public static Server newServer( config.setSendServerVersion(false); config.setSendXPoweredBy(false); + return connector; + } + + public static void insertHandlers(Server server) { SizeLimitHandler sizeLimitHandler = new SizeLimitHandler(MAX_REQUEST_SIZE, -1); - sizeLimitHandler.setHandler(handler); + sizeLimitHandler.setHandler(server.getHandler()); GzipHandler gzip = new GzipHandler(); gzip.setInflateBufferSize(8 * 1024); gzip.setHandler(sizeLimitHandler); gzip.setExcludedAgentPatterns(); + gzip.setIncludedMethods(); // Include all methods for the GzipHandler. + server.setHandler(gzip); + } - // Include all methods for the GzipHandler. - gzip.setIncludedMethods(); + public static Server newServer( + ServletEngineAdapter.Config runtimeOptions, ForwardingHandler handler) { + Server server = new Server(); + server.setHandler(handler); + insertHandlers(server); - server.setHandler(gzip); + ServerConnector connector = newConnector(server, runtimeOptions); + server.addConnector(connector); logger.atInfo().log("Starting Jetty http server for Java runtime proxy."); return server; @@ -135,39 +143,19 @@ public static class ForwardingHandler extends AbstractHandler { private static final String X_APPENGINE_TIMEOUT_MS = "x-appengine-timeout-ms"; - private final String applicationRoot; - private final String fixedApplicationPath; - private final AppInfoFactory appInfoFactory; private final EvaluationRuntimeServerInterface evaluationRuntimeServerInterface; private final UPRequestTranslator upRequestTranslator; - public ForwardingHandler(ServletEngineAdapter.Config runtimeOptions, Map env) - throws ExecutionException, InterruptedException, IOException { - this.applicationRoot = runtimeOptions.applicationRoot(); - this.fixedApplicationPath = runtimeOptions.fixedApplicationPath(); - this.appInfoFactory = new AppInfoFactory(env); + public ForwardingHandler(ServletEngineAdapter.Config runtimeOptions, Map env) { + AppInfoFactory appInfoFactory = new AppInfoFactory(env); this.evaluationRuntimeServerInterface = runtimeOptions.evaluationRuntimeServerInterface(); this.upRequestTranslator = new UPRequestTranslator( - this.appInfoFactory, + appInfoFactory, runtimeOptions.passThroughPrivateHeaders(), /*skipPostData=*/ false); } - private void init() { - /* The init actions are not done in the constructor as they are not used when testing */ - try { - AppinfoPb.AppInfo appinfo = - appInfoFactory.getAppInfoFromFile(applicationRoot, fixedApplicationPath); - // TODO Should we also call ApplyCloneSettings()? - LocalRpcContext context = new LocalRpcContext<>(EmptyMessage.class); - evaluationRuntimeServerInterface.addAppVersion(context, appinfo); - Object unused = context.getResponse(); - } catch (Exception e) { - throw new IllegalStateException(e); - } - } - /** * Forwards a request to the real runtime for handling. We translate the javax.servlet types * into protocol buffers and send the request, then translate the response proto back to a diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyServletEngineAdapter.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyServletEngineAdapter.java index b1b205310..2f1ab75b6 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyServletEngineAdapter.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyServletEngineAdapter.java @@ -16,15 +16,19 @@ package com.google.apphosting.runtime.jetty9; +import static com.google.apphosting.runtime.AppEngineConstants.HTTP_CONNECTOR_MODE; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.apphosting.base.AppVersionKey; import com.google.apphosting.base.protos.AppinfoPb; +import com.google.apphosting.base.protos.EmptyMessage; import com.google.apphosting.base.protos.RuntimePb.UPRequest; import com.google.apphosting.base.protos.RuntimePb.UPResponse; import com.google.apphosting.runtime.AppVersion; +import com.google.apphosting.runtime.LocalRpcContext; import com.google.apphosting.runtime.MutableUpResponse; import com.google.apphosting.runtime.ServletEngineAdapter; +import com.google.apphosting.runtime.anyrpc.EvaluationRuntimeServerInterface; import com.google.apphosting.utils.config.AppEngineConfigException; import com.google.apphosting.utils.config.AppYaml; import com.google.common.flogger.GoogleLogger; @@ -38,6 +42,7 @@ import javax.servlet.ServletException; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.handler.SizeLimitHandler; import org.eclipse.jetty.util.thread.QueuedThreadPool; @@ -113,20 +118,58 @@ public void start(String serverInfo, ServletEngineAdapter.Config runtimeOptions) server.setHandler(appVersionHandlerMap); } + boolean startJettyHttpProxy = false; if (runtimeOptions.useJettyHttpProxy()) { - server.setAttribute( - "com.google.apphosting.runtime.jetty9.appYaml", - appYaml.orElseGet(() -> JettyServletEngineAdapter.getAppYaml(runtimeOptions))); - JettyHttpProxy.startServer(runtimeOptions); + AppInfoFactory appInfoFactory; + AppVersionKey appVersionKey; + /* The init actions are not done in the constructor as they are not used when testing */ + try { + String appRoot = runtimeOptions.applicationRoot(); + String appPath = runtimeOptions.fixedApplicationPath(); + appInfoFactory = new AppInfoFactory(System.getenv()); + AppinfoPb.AppInfo appinfo = appInfoFactory.getAppInfoFromFile(appRoot, appPath); + // TODO Should we also call ApplyCloneSettings()? + LocalRpcContext context = new LocalRpcContext<>(EmptyMessage.class); + EvaluationRuntimeServerInterface evaluationRuntimeServerInterface = + Objects.requireNonNull(runtimeOptions.evaluationRuntimeServerInterface()); + evaluationRuntimeServerInterface.addAppVersion(context, appinfo); + context.getResponse(); + appVersionKey = AppVersionKey.fromAppInfo(appinfo); + appVersionHandlerMap.getHandler(appVersionKey); + } catch (Exception e) { + throw new IllegalStateException(e); + } + if (Boolean.getBoolean(HTTP_CONNECTOR_MODE)) { + logger.atInfo().log("Using HTTP_CONNECTOR_MODE to bypass RPC"); + JettyHttpProxy.insertHandlers(server); + AppVersion appVersion = appVersionHandlerMap.getAppVersion(appVersionKey); + server.insertHandler(new JettyHttpHandler(runtimeOptions, appVersion, appVersionKey, appInfoFactory)); + ServerConnector connector = JettyHttpProxy.newConnector(server, runtimeOptions); + server.addConnector(connector); + } else { + server.setAttribute( + "com.google.apphosting.runtime.jetty9.appYaml", + appYaml.orElseGet(() -> JettyServletEngineAdapter.getAppYaml(runtimeOptions))); + // Delay start of JettyHttpProxy until after the main server and application is started. + startJettyHttpProxy = true; + } } + ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(JettyServletEngineAdapter.class.getClassLoader()); try { server.start(); + if (startJettyHttpProxy) { + JettyHttpProxy.startServer(runtimeOptions); + } } catch (Exception ex) { // TODO: Should we have a wrapper exception for this // type of thing in ServletEngineAdapter? throw new RuntimeException(ex); } + finally { + Thread.currentThread().setContextClassLoader(oldContextClassLoader); + } } @Override @@ -152,7 +195,7 @@ public void deleteAppVersion(AppVersion appVersion) { * Sets the {@link com.google.apphosting.runtime.SessionStoreFactory} that will be used to create * the list of {@link com.google.apphosting.runtime.SessionStore SessionStores} to which the HTTP * Session will be stored, if sessions are enabled. This method must be invoked after {@link - * #start(String)}. + * #start(String, Config)}. */ @Override public void setSessionStoreFactory(com.google.apphosting.runtime.SessionStoreFactory factory) { From 7fcee296488ac7ec29ba4ce065b08c9b705d5179 Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Thu, 27 Jun 2024 10:06:59 -0700 Subject: [PATCH 16/28] Update dependencies for appengine-java-standard. PiperOrigin-RevId: 647357811 Change-Id: Ifbb9a795bcc72e4f2e39181bf97f44a466bc74ff --- applications/proberapp/pom.xml | 20 ++++++++++---------- jetty12_assembly/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/applications/proberapp/pom.xml b/applications/proberapp/pom.xml index 204a54122..dcf50f271 100644 --- a/applications/proberapp/pom.xml +++ b/applications/proberapp/pom.xml @@ -38,7 +38,7 @@ us-central1 prober-user prober_connectivity_test_database - + 2.50.0 ${project.version} UTF-8 target/${project.artifactId}-${project.version} @@ -58,22 +58,22 @@ com.google.cloud google-cloud-spanner - 6.69.0 + 6.70.0 com.google.api gax - 2.49.0 + ${gax.version} com.google.api gax-httpjson - 2.49.0 + ${gax.version} com.google.api gax-grpc - 2.49.0 + ${gax.version} com.google.api-client @@ -86,12 +86,12 @@ com.google.cloud google-cloud-bigquery - 2.40.3 + 2.41.0 com.google.cloud google-cloud-core - 2.39.0 + 2.40.0 com.google.cloud @@ -101,12 +101,12 @@ com.google.cloud google-cloud-logging - 3.18.0 + 3.19.0 com.google.cloud google-cloud-storage - 2.40.0 + 2.40.1 com.google.cloud.sql @@ -281,4 +281,4 @@ - + \ No newline at end of file diff --git a/jetty12_assembly/pom.xml b/jetty12_assembly/pom.xml index 1c3f15b5b..c8a052c68 100644 --- a/jetty12_assembly/pom.xml +++ b/jetty12_assembly/pom.xml @@ -36,7 +36,7 @@ maven-dependency-plugin - 3.7.0 + 3.7.1 unpack diff --git a/pom.xml b/pom.xml index 6afab428f..d3e340b02 100644 --- a/pom.xml +++ b/pom.xml @@ -777,7 +777,7 @@ com.google.cloud google-cloud-logging - 3.18.0 + 3.19.0 From a1db93c719cc918dbb1c4a8d0a395d1f179f823b Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Thu, 27 Jun 2024 12:54:51 -0700 Subject: [PATCH 17/28] refactor com.google.apphosting.runtime.AppEngineConstants to be shared with Jetty9 and Jetty12. PiperOrigin-RevId: 647416748 Change-Id: Ia55bfc4890f8d0937f21b905140e8c7eb4770523 --- .../runtime}/AppEngineConstants.java | 27 ++++- .../apphosting/runtime/JettyConstants.java | 40 ------- .../jetty/JettyServletEngineAdapter.java | 24 ++-- .../ee10/EE10AppVersionHandlerFactory.java | 19 ++-- .../jetty/ee10/ResourceFileServlet.java | 8 +- .../ee8/EE8AppVersionHandlerFactory.java | 27 +++-- .../jetty/ee8/ResourceFileServlet.java | 8 +- .../runtime/jetty/http/JettyHttpHandler.java | 25 ++--- .../jetty/http/JettyRequestAPIData.java | 61 +++++----- .../jetty/proxy/UPRequestTranslator.java | 60 +++++----- .../jetty9/AppVersionHandlerFactory.java | 6 +- .../runtime/jetty9/AppVersionHandlerMap.java | 4 +- .../runtime/jetty9/ResourceFileServlet.java | 8 +- .../runtime/jetty9/RpcConnection.java | 4 +- .../runtime/jetty9/UPRequestTranslator.java | 106 +++++++----------- 15 files changed, 186 insertions(+), 241 deletions(-) rename runtime/{runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty => impl/src/main/java/com/google/apphosting/runtime}/AppEngineConstants.java (80%) delete mode 100644 runtime/impl/src/main/java/com/google/apphosting/runtime/JettyConstants.java diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/AppEngineConstants.java b/runtime/impl/src/main/java/com/google/apphosting/runtime/AppEngineConstants.java similarity index 80% rename from runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/AppEngineConstants.java rename to runtime/impl/src/main/java/com/google/apphosting/runtime/AppEngineConstants.java index 3136ce11c..95f5c0bb3 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/AppEngineConstants.java +++ b/runtime/impl/src/main/java/com/google/apphosting/runtime/AppEngineConstants.java @@ -14,11 +14,29 @@ * limitations under the License. */ -package com.google.apphosting.runtime.jetty; +package com.google.apphosting.runtime; import com.google.common.collect.ImmutableSet; +/** {@code AppEngineConstants} centralizes some constants that are specific to our use of Jetty. */ public final class AppEngineConstants { + /** + * This {@code ServletContext} attribute contains the {@link AppVersion} for the current + * application. + */ + public static final String APP_VERSION_CONTEXT_ATTR = + "com.google.apphosting.runtime.jetty.APP_VERSION_CONTEXT_ATTR"; + + /** + * This {@code ServletRequest} attribute contains the {@code AppVersionKey} identifying the + * current application. identify which application version to use. + */ + public static final String APP_VERSION_KEY_REQUEST_ATTR = + "com.google.apphosting.runtime.jetty.APP_VERSION_REQUEST_ATTR"; + + public static final String APP_YAML_ATTRIBUTE_TARGET = + "com.google.apphosting.runtime.jetty.appYaml"; + /** * The HTTP headers that are handled specially by this proxy are defined in lowercase because HTTP * headers are case-insensitive, and we look then up in a set or switch after converting to @@ -54,6 +72,11 @@ public final class AppEngineConstants { public static final String X_GOOGLE_INTERNAL_PROFILER = "x-google-internal-profiler"; public static final String X_CLOUD_TRACE_CONTEXT = "x-cloud-trace-context"; + public static final String X_APPENGINE_BACKGROUNDREQUEST = "x-appengine-backgroundrequest"; + public static final String BACKGROUND_REQUEST_URL = "/_ah/background"; + public static final String WARMUP_REQUEST_URL = "/_ah/start"; + public static final String BACKGROUND_REQUEST_SOURCE_IP = "0.1.0.3"; + public static final ImmutableSet PRIVATE_APPENGINE_HEADERS = ImmutableSet.of( X_APPENGINE_API_TICKET, @@ -91,4 +114,6 @@ public final class AppEngineConstants { public static final String ENVIRONMENT_ATTR = "appengine.environment"; public static final String HTTP_CONNECTOR_MODE = "appengine.use.HttpConnector"; + + private AppEngineConstants() {} } diff --git a/runtime/impl/src/main/java/com/google/apphosting/runtime/JettyConstants.java b/runtime/impl/src/main/java/com/google/apphosting/runtime/JettyConstants.java deleted file mode 100644 index 7896f32d5..000000000 --- a/runtime/impl/src/main/java/com/google/apphosting/runtime/JettyConstants.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * 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 - * - * https://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.apphosting.runtime; - -/** {@code JettyConstants} centralizes some constants that are specific to our use of Jetty. */ -public final class JettyConstants { - /** - * This {@link ServletContext} attribute contains the {@link - * AppVersion} for the current application. - */ - public static final String APP_VERSION_CONTEXT_ATTR = - "com.google.apphosting.runtime.jetty.APP_VERSION_CONTEXT_ATTR"; - - /** - * This {@code ServletRequest} attribute contains the {@link - * AppVersionKey} identifying the current application. identify - * which application version to use. - */ - public static final String APP_VERSION_KEY_REQUEST_ATTR = - "com.google.apphosting.runtime.jetty.APP_VERSION_REQUEST_ATTR"; - - public static final String APP_YAML_ATTRIBUTE_TARGET = - "com.google.apphosting.runtime.jetty.appYaml"; - - private JettyConstants() {} -} diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java index efd995279..ff135be9b 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java @@ -15,14 +15,18 @@ */ package com.google.apphosting.runtime.jetty; +import static com.google.apphosting.runtime.AppEngineConstants.HTTP_CONNECTOR_MODE; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.google.apphosting.api.ApiProxy; import com.google.apphosting.base.AppVersionKey; import com.google.apphosting.base.protos.AppinfoPb; import com.google.apphosting.base.protos.EmptyMessage; import com.google.apphosting.base.protos.RuntimePb.UPRequest; import com.google.apphosting.base.protos.RuntimePb.UPResponse; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.MutableUpResponse; import com.google.apphosting.runtime.ServletEngineAdapter; import com.google.apphosting.runtime.anyrpc.EvaluationRuntimeServerInterface; @@ -34,6 +38,12 @@ import com.google.apphosting.utils.config.AppEngineConfigException; import com.google.apphosting.utils.config.AppYaml; import com.google.common.flogger.GoogleLogger; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStreamReader; +import java.util.Objects; +import java.util.concurrent.ExecutionException; import org.eclipse.jetty.http.CookieCompliance; import org.eclipse.jetty.http.UriCompliance; import org.eclipse.jetty.server.HttpConfiguration; @@ -44,16 +54,6 @@ import org.eclipse.jetty.util.resource.ResourceFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStreamReader; -import java.util.Objects; -import java.util.concurrent.ExecutionException; - -import static com.google.apphosting.runtime.jetty.AppEngineConstants.HTTP_CONNECTOR_MODE; -import static java.nio.charset.StandardCharsets.UTF_8; - /** * This is an implementation of ServletEngineAdapter that uses the third-party Jetty servlet engine. * @@ -269,7 +269,7 @@ public void serviceRequest(UPRequest upRequest, MutableUpResponse upResponse) th httpConfiguration.setUriCompliance(UriCompliance.LEGACY); } DelegateRpcExchange rpcExchange = new DelegateRpcExchange(upRequest, upResponse); - rpcExchange.setAttribute(JettyConstants.APP_VERSION_KEY_REQUEST_ATTR, appVersionKey); + rpcExchange.setAttribute(AppEngineConstants.APP_VERSION_KEY_REQUEST_ATTR, appVersionKey); rpcExchange.setAttribute(AppEngineConstants.ENVIRONMENT_ATTR, ApiProxy.getCurrentEnvironment()); rpcConnector.service(rpcExchange); try { diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/EE10AppVersionHandlerFactory.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/EE10AppVersionHandlerFactory.java index e64f98f35..4cad8edd8 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/EE10AppVersionHandlerFactory.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/EE10AppVersionHandlerFactory.java @@ -15,11 +15,13 @@ */ package com.google.apphosting.runtime.jetty.ee10; +import static com.google.apphosting.runtime.AppEngineConstants.HTTP_CONNECTOR_MODE; + import com.google.apphosting.api.ApiProxy; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.SessionsConfig; -import com.google.apphosting.runtime.jetty.AppEngineConstants; import com.google.apphosting.runtime.jetty.AppVersionHandlerFactory; import com.google.apphosting.runtime.jetty.EE10SessionManagerHandler; import com.google.common.flogger.GoogleLogger; @@ -29,6 +31,10 @@ import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import javax.servlet.jsp.JspFactory; import org.eclipse.jetty.ee10.annotations.AnnotationConfiguration; import org.eclipse.jetty.ee10.quickstart.QuickStartConfiguration; import org.eclipse.jetty.ee10.servlet.Dispatcher; @@ -48,13 +54,6 @@ import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.Callback; -import javax.servlet.jsp.JspFactory; -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; - -import static com.google.apphosting.runtime.jetty.AppEngineConstants.HTTP_CONNECTOR_MODE; - /** * {@code AppVersionHandlerFactory} implements a {@code Handler} for a given {@code AppVersionKey}. */ @@ -191,7 +190,7 @@ private org.eclipse.jetty.server.Handler doCreateHandler(AppVersion appVersion) .setServletContextHandler(context); EE10SessionManagerHandler.create(builder.build()); // Pass the AppVersion on to any of our servlets (e.g. ResourceFileServlet). - context.setAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR, appVersion); + context.setAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR, appVersion); if (Boolean.getBoolean(HTTP_CONNECTOR_MODE)) { context.addEventListener( diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/ResourceFileServlet.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/ResourceFileServlet.java index 129190741..93c4f42d9 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/ResourceFileServlet.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee10/ResourceFileServlet.java @@ -17,7 +17,7 @@ package com.google.apphosting.runtime.jetty.ee10; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.utils.config.AppYaml; import com.google.common.base.Ascii; import com.google.common.flogger.GoogleLogger; @@ -71,11 +71,11 @@ public class ResourceFileServlet extends HttpServlet { public void init() throws ServletException { context = getServletContext(); AppVersion appVersion = - (AppVersion) context.getAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR); + (AppVersion) context.getAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR); chandler = ServletContextHandler.getServletContextHandler(context); AppYaml appYaml = - (AppYaml) chandler.getServer().getAttribute(JettyConstants.APP_YAML_ATTRIBUTE_TARGET); + (AppYaml) chandler.getServer().getAttribute(AppEngineConstants.APP_YAML_ATTRIBUTE_TARGET); fSender = new FileSender(appYaml); // AFAICT, there is no real API to retrieve this information, so // we access Jetty's internal state. @@ -261,7 +261,7 @@ private boolean maybeServeWelcomeFile( } AppVersion appVersion = - (AppVersion) getServletContext().getAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR); + (AppVersion) getServletContext().getAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR); ServletHandler handler = chandler.getServletHandler(); for (String welcomeName : welcomeFiles) { diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/EE8AppVersionHandlerFactory.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/EE8AppVersionHandlerFactory.java index 9c117306a..301c5eec5 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/EE8AppVersionHandlerFactory.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/EE8AppVersionHandlerFactory.java @@ -16,15 +16,25 @@ package com.google.apphosting.runtime.jetty.ee8; +import static com.google.apphosting.runtime.AppEngineConstants.HTTP_CONNECTOR_MODE; + import com.google.apphosting.api.ApiProxy; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.SessionsConfig; -import com.google.apphosting.runtime.jetty.AppEngineConstants; import com.google.apphosting.runtime.jetty.AppVersionHandlerFactory; import com.google.apphosting.runtime.jetty.SessionManagerHandler; import com.google.common.flogger.GoogleLogger; import com.google.common.html.HtmlEscapers; +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.jsp.JspFactory; import org.eclipse.jetty.ee8.annotations.AnnotationConfiguration; import org.eclipse.jetty.ee8.nested.ContextHandler; import org.eclipse.jetty.ee8.nested.Dispatcher; @@ -37,17 +47,6 @@ import org.eclipse.jetty.ee8.webapp.WebXmlConfiguration; import org.eclipse.jetty.server.Server; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.jsp.JspFactory; -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; - -import static com.google.apphosting.runtime.jetty.AppEngineConstants.HTTP_CONNECTOR_MODE; - /** * {@code AppVersionHandlerFactory} implements a {@code Handler} for a given {@code AppVersionKey}. */ @@ -205,7 +204,7 @@ private org.eclipse.jetty.server.Handler doCreateHandler(AppVersion appVersion) SessionManagerHandler.create(builder.build()); // Pass the AppVersion on to any of our servlets (e.g. ResourceFileServlet). - context.setAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR, appVersion); + context.setAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR, appVersion); if (Boolean.getBoolean(HTTP_CONNECTOR_MODE)) { context.addEventListener( diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/ResourceFileServlet.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/ResourceFileServlet.java index 2d949dd9b..f79c6ded5 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/ResourceFileServlet.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/ResourceFileServlet.java @@ -17,7 +17,7 @@ package com.google.apphosting.runtime.jetty.ee8; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.utils.config.AppYaml; import com.google.common.base.Ascii; import com.google.common.flogger.GoogleLogger; @@ -68,11 +68,11 @@ public class ResourceFileServlet extends HttpServlet { public void init() throws ServletException { context = getServletContext(); AppVersion appVersion = - (AppVersion) context.getAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR); + (AppVersion) context.getAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR); chandler = ContextHandler.getContextHandler(context); AppYaml appYaml = - (AppYaml) chandler.getServer().getAttribute(JettyConstants.APP_YAML_ATTRIBUTE_TARGET); + (AppYaml) chandler.getServer().getAttribute(AppEngineConstants.APP_YAML_ATTRIBUTE_TARGET); fSender = new FileSender(appYaml); // AFAICT, there is no real API to retrieve this information, so // we access Jetty's internal state. @@ -251,7 +251,7 @@ private boolean maybeServeWelcomeFile( } AppVersion appVersion = - (AppVersion) getServletContext().getAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR); + (AppVersion) getServletContext().getAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR); ServletHandler handler = chandler.getChildHandlerByClass(ServletHandler.class); MappedResource defaultEntry = handler.getHolderEntry("/"); diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyHttpHandler.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyHttpHandler.java index 64a357ce5..3c9efd382 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyHttpHandler.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyHttpHandler.java @@ -16,42 +16,37 @@ package com.google.apphosting.runtime.jetty.http; +import static com.google.apphosting.runtime.RequestRunner.WAIT_FOR_USER_RUNNABLE_DEADLINE; + import com.google.appengine.api.ThreadManager; import com.google.apphosting.api.ApiProxy; import com.google.apphosting.base.AppVersionKey; import com.google.apphosting.base.protos.EmptyMessage; import com.google.apphosting.base.protos.RuntimePb; import com.google.apphosting.runtime.ApiProxyImpl; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.AppVersion; import com.google.apphosting.runtime.BackgroundRequestCoordinator; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.RequestManager; -import com.google.apphosting.runtime.RequestRunner; import com.google.apphosting.runtime.RequestRunner.EagerRunner; import com.google.apphosting.runtime.ResponseAPIData; import com.google.apphosting.runtime.ServletEngineAdapter; -import com.google.apphosting.runtime.jetty.AppEngineConstants; import com.google.apphosting.runtime.jetty.AppInfoFactory; import com.google.common.base.Ascii; import com.google.common.flogger.GoogleLogger; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.time.Duration; +import java.util.Optional; +import java.util.concurrent.TimeoutException; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; -import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.Blocker; import org.eclipse.jetty.util.Callback; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.time.Duration; -import java.util.Optional; -import java.util.concurrent.TimeoutException; - -import static com.google.apphosting.runtime.RequestRunner.WAIT_FOR_USER_RUNNABLE_DEADLINE; -import java.util.concurrent.Exchanger; -import static java.util.concurrent.TimeUnit.MILLISECONDS; - /** * This class replicates the behaviour of the {@link RequestRunner} for Requests which do not come * through RPC. It should be added as a {@link Handler} to the Jetty {@link Server} wrapping the @@ -168,7 +163,7 @@ private boolean dispatchServletRequest( throws Throwable { Request jettyRequest = request.getWrappedRequest(); Response jettyResponse = response.getWrappedResponse(); - jettyRequest.setAttribute(JettyConstants.APP_VERSION_KEY_REQUEST_ATTR, appVersionKey); + jettyRequest.setAttribute(AppEngineConstants.APP_VERSION_KEY_REQUEST_ATTR, appVersionKey); // Environment is set in a request attribute which is set/unset for async threads by // a ContextScopeListener created inside the AppVersionHandlerFactory. diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyRequestAPIData.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyRequestAPIData.java index 6c56ac139..50a50d1f1 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyRequestAPIData.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyRequestAPIData.java @@ -17,43 +17,42 @@ package com.google.apphosting.runtime.jetty.http; import static com.google.apphosting.base.protos.RuntimePb.UPRequest.RequestType.OTHER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.DEFAULT_SECRET_KEY; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.IS_ADMIN_HEADER_VALUE; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.IS_TRUSTED; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.PRIVATE_APPENGINE_HEADERS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.SKIP_ADMIN_CHECK_ATTR; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.WARMUP_IP; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_API_TICKET; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_APPSERVER_DATACENTER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_APPSERVER_TASK_BNS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_AUTH_DOMAIN; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_DEFAULT_VERSION_HOSTNAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_GAIA_AUTHUSER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_GAIA_ID; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_GAIA_SESSION; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_HTTPS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_ID_HASH; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_LOAS_PEER_USERNAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_QUEUENAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_REQUEST_LOG_ID; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_TIMEOUT_MS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_TRUSTED_IP_REQUEST; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_EMAIL; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_ID; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_IP; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_IS_ADMIN; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_ORGANIZATION; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_CLOUD_TRACE_CONTEXT; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_FORWARDED_PROTO; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_GOOGLE_INTERNAL_PROFILER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK; +import static com.google.apphosting.runtime.AppEngineConstants.DEFAULT_SECRET_KEY; +import static com.google.apphosting.runtime.AppEngineConstants.IS_ADMIN_HEADER_VALUE; +import static com.google.apphosting.runtime.AppEngineConstants.IS_TRUSTED; +import static com.google.apphosting.runtime.AppEngineConstants.PRIVATE_APPENGINE_HEADERS; +import static com.google.apphosting.runtime.AppEngineConstants.SKIP_ADMIN_CHECK_ATTR; +import static com.google.apphosting.runtime.AppEngineConstants.WARMUP_IP; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_API_TICKET; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_DATACENTER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_TASK_BNS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_AUTH_DOMAIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_DEFAULT_VERSION_HOSTNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_AUTHUSER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_SESSION; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_HTTPS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_ID_HASH; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_LOAS_PEER_USERNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_QUEUENAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_REQUEST_LOG_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TIMEOUT_MS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TRUSTED_IP_REQUEST; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_EMAIL; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IP; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IS_ADMIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ORGANIZATION; +import static com.google.apphosting.runtime.AppEngineConstants.X_CLOUD_TRACE_CONTEXT; +import static com.google.apphosting.runtime.AppEngineConstants.X_FORWARDED_PROTO; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_PROFILER; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK; import com.google.apphosting.base.protos.HttpPb; import com.google.apphosting.base.protos.RuntimePb; import com.google.apphosting.base.protos.TracePb; import com.google.apphosting.runtime.RequestAPIData; import com.google.apphosting.runtime.TraceContextHelper; -import com.google.apphosting.runtime.jetty.AppEngineConstants; import com.google.apphosting.runtime.jetty.AppInfoFactory; import com.google.common.base.Strings; import com.google.common.flogger.GoogleLogger; diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/UPRequestTranslator.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/UPRequestTranslator.java index ee2d5d66e..5ab288c1f 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/UPRequestTranslator.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/UPRequestTranslator.java @@ -16,36 +16,36 @@ package com.google.apphosting.runtime.jetty.proxy; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.DEFAULT_SECRET_KEY; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.IS_ADMIN_HEADER_VALUE; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.IS_TRUSTED; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.PRIVATE_APPENGINE_HEADERS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.WARMUP_IP; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_API_TICKET; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_APPSERVER_DATACENTER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_APPSERVER_TASK_BNS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_AUTH_DOMAIN; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_DEFAULT_VERSION_HOSTNAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_GAIA_AUTHUSER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_GAIA_ID; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_GAIA_SESSION; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_HTTPS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_LOAS_PEER_USERNAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_QUEUENAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_REQUEST_LOG_ID; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_TIMEOUT_MS; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_TRUSTED_IP_REQUEST; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_EMAIL; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_ID; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_IP; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_IS_ADMIN; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_NICKNAME; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_APPENGINE_USER_ORGANIZATION; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_CLOUD_TRACE_CONTEXT; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_FORWARDED_PROTO; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_GOOGLE_INTERNAL_PROFILER; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK; -import static com.google.apphosting.runtime.jetty.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK_UC; +import static com.google.apphosting.runtime.AppEngineConstants.DEFAULT_SECRET_KEY; +import static com.google.apphosting.runtime.AppEngineConstants.IS_ADMIN_HEADER_VALUE; +import static com.google.apphosting.runtime.AppEngineConstants.IS_TRUSTED; +import static com.google.apphosting.runtime.AppEngineConstants.PRIVATE_APPENGINE_HEADERS; +import static com.google.apphosting.runtime.AppEngineConstants.WARMUP_IP; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_API_TICKET; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_DATACENTER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_TASK_BNS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_AUTH_DOMAIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_DEFAULT_VERSION_HOSTNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_AUTHUSER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_SESSION; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_HTTPS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_LOAS_PEER_USERNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_QUEUENAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_REQUEST_LOG_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TIMEOUT_MS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TRUSTED_IP_REQUEST; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_EMAIL; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IP; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IS_ADMIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_NICKNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ORGANIZATION; +import static com.google.apphosting.runtime.AppEngineConstants.X_CLOUD_TRACE_CONTEXT; +import static com.google.apphosting.runtime.AppEngineConstants.X_FORWARDED_PROTO; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_PROFILER; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK_UC; import com.google.apphosting.base.protos.AppinfoPb; import com.google.apphosting.base.protos.HttpPb; diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerFactory.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerFactory.java index b47d25a3b..f232e3375 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerFactory.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerFactory.java @@ -16,9 +16,8 @@ package com.google.apphosting.runtime.jetty9; -import com.google.apphosting.base.AppVersionKey; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.SessionsConfig; import com.google.common.collect.ImmutableList; import com.google.common.flogger.GoogleLogger; @@ -141,7 +140,6 @@ private final String[] getPreconfigurationClasses() { } private Handler doCreateHandler(AppVersion appVersion) throws ServletException { - AppVersionKey appVersionKey = appVersion.getKey(); try { File contextRoot = appVersion.getRootDirectory(); @@ -200,7 +198,7 @@ private Handler doCreateHandler(AppVersion appVersion) throws ServletException { SessionManagerHandler unused = SessionManagerHandler.create(builder.build()); // Pass the AppVersion on to any of our servlets (e.g. ResourceFileServlet). - context.setAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR, appVersion); + context.setAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR, appVersion); context.start(); // Check to see if servlet filter initialization failed. diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerMap.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerMap.java index 9a2b7d191..5d63b6a6d 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerMap.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/AppVersionHandlerMap.java @@ -18,7 +18,7 @@ import com.google.apphosting.base.AppVersionKey; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.SessionStore; import com.google.apphosting.runtime.SessionStoreFactory; import org.eclipse.jetty.server.Handler; @@ -104,7 +104,7 @@ public void handle( String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { AppVersionKey appVersionKey = - (AppVersionKey) request.getAttribute(JettyConstants.APP_VERSION_KEY_REQUEST_ATTR); + (AppVersionKey) request.getAttribute(AppEngineConstants.APP_VERSION_KEY_REQUEST_ATTR); if (appVersionKey == null) { throw new ServletException("Request did not provide an application version"); } diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/ResourceFileServlet.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/ResourceFileServlet.java index 68bddac18..6cea7c23e 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/ResourceFileServlet.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/ResourceFileServlet.java @@ -17,7 +17,7 @@ package com.google.apphosting.runtime.jetty9; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.utils.config.AppYaml; import com.google.common.base.Ascii; import com.google.common.flogger.GoogleLogger; @@ -68,11 +68,11 @@ public class ResourceFileServlet extends HttpServlet { public void init() throws ServletException { context = getServletContext(); AppVersion appVersion = - (AppVersion) context.getAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR); + (AppVersion) context.getAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR); chandler = ((ContextHandler.Context) context).getContextHandler(); AppYaml appYaml = - (AppYaml) chandler.getServer().getAttribute(JettyConstants.APP_YAML_ATTRIBUTE_TARGET); + (AppYaml) chandler.getServer().getAttribute(AppEngineConstants.APP_YAML_ATTRIBUTE_TARGET); fSender = new FileSender(appYaml); // AFAICT, there is no real API to retrieve this information, so // we access Jetty's internal state. @@ -250,7 +250,7 @@ private boolean maybeServeWelcomeFile( } AppVersion appVersion = - (AppVersion) getServletContext().getAttribute(JettyConstants.APP_VERSION_CONTEXT_ATTR); + (AppVersion) getServletContext().getAttribute(AppEngineConstants.APP_VERSION_CONTEXT_ATTR); ServletHandler handler = chandler.getChildHandlerByClass(ServletHandler.class); MappedResource defaultEntry = handler.getHolderEntry("/"); diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/RpcConnection.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/RpcConnection.java index ad5c18ac6..e69f7797d 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/RpcConnection.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/RpcConnection.java @@ -21,7 +21,7 @@ import com.google.apphosting.base.protos.HttpPb.ParsedHttpHeader; import com.google.apphosting.base.protos.RuntimePb.UPRequest; import com.google.apphosting.base.protos.RuntimePb.UPResponse; -import com.google.apphosting.runtime.JettyConstants; +import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.MutableUpResponse; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Ascii; @@ -245,7 +245,7 @@ public void onCompleted() { // Tell AppVersionHandlerMap which app version should handle this // request. - request.setAttribute(JettyConstants.APP_VERSION_KEY_REQUEST_ATTR, appVersionKey); + request.setAttribute(AppEngineConstants.APP_VERSION_KEY_REQUEST_ATTR, appVersionKey); final boolean skipAdmin = hasSkipAdminCheck(endPoint.getUpRequest()); // Translate the X-Google-Internal-SkipAdminCheck to a servlet attribute. diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/UPRequestTranslator.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/UPRequestTranslator.java index 4cdef9797..a1d8e0200 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/UPRequestTranslator.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/UPRequestTranslator.java @@ -16,6 +16,38 @@ package com.google.apphosting.runtime.jetty9; +import static com.google.apphosting.runtime.AppEngineConstants.BACKGROUND_REQUEST_URL; +import static com.google.apphosting.runtime.AppEngineConstants.IS_ADMIN_HEADER_VALUE; +import static com.google.apphosting.runtime.AppEngineConstants.IS_TRUSTED; +import static com.google.apphosting.runtime.AppEngineConstants.PRIVATE_APPENGINE_HEADERS; +import static com.google.apphosting.runtime.AppEngineConstants.WARMUP_IP; +import static com.google.apphosting.runtime.AppEngineConstants.WARMUP_REQUEST_URL; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_API_TICKET; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_DATACENTER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_APPSERVER_TASK_BNS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_AUTH_DOMAIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_DEFAULT_VERSION_HOSTNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_AUTHUSER; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_GAIA_SESSION; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_HTTPS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_LOAS_PEER_USERNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_QUEUENAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_REQUEST_LOG_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TIMEOUT_MS; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_TRUSTED_IP_REQUEST; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_EMAIL; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ID; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IP; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_IS_ADMIN; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_NICKNAME; +import static com.google.apphosting.runtime.AppEngineConstants.X_APPENGINE_USER_ORGANIZATION; +import static com.google.apphosting.runtime.AppEngineConstants.X_CLOUD_TRACE_CONTEXT; +import static com.google.apphosting.runtime.AppEngineConstants.X_FORWARDED_PROTO; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_PROFILER; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK; +import static com.google.apphosting.runtime.AppEngineConstants.X_GOOGLE_INTERNAL_SKIPADMINCHECK_UC; + import com.google.apphosting.base.protos.AppinfoPb; import com.google.apphosting.base.protos.HttpPb; import com.google.apphosting.base.protos.HttpPb.HttpRequest; @@ -26,13 +58,13 @@ import com.google.apphosting.runtime.TraceContextHelper; import com.google.common.base.Ascii; import com.google.common.base.Strings; -import com.google.common.collect.ImmutableSet; import com.google.common.flogger.GoogleLogger; import com.google.common.html.HtmlEscapers; import com.google.protobuf.ByteString; import com.google.protobuf.TextFormat; import java.io.IOException; import java.util.Collections; +import java.util.Objects; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -46,69 +78,7 @@ public class UPRequestTranslator { private static final String DEFAULT_SECRET_KEY = "secretkey"; - /** - * The HTTP headers that are handled specially by this proxy are defined in lowercae because HTTP - * headers are case insensitive and we look then up in a set or switch after converting to - * lower-case. - */ - private static final String X_FORWARDED_PROTO = "x-forwarded-proto"; - - private static final String X_APPENGINE_API_TICKET = "x-appengine-api-ticket"; - private static final String X_APPENGINE_HTTPS = "x-appengine-https"; - private static final String X_APPENGINE_USER_IP = "x-appengine-user-ip"; - private static final String X_APPENGINE_USER_EMAIL = "x-appengine-user-email"; - private static final String X_APPENGINE_AUTH_DOMAIN = "x-appengine-auth-domain"; - private static final String X_APPENGINE_USER_ID = "x-appengine-user-id"; - private static final String X_APPENGINE_USER_NICKNAME = "x-appengine-user-nickname"; - private static final String X_APPENGINE_USER_ORGANIZATION = "x-appengine-user-organization"; - private static final String X_APPENGINE_USER_IS_ADMIN = "x-appengine-user-is-admin"; - private static final String X_APPENGINE_TRUSTED_IP_REQUEST = "x-appengine-trusted-ip-request"; - private static final String X_APPENGINE_LOAS_PEER_USERNAME = "x-appengine-loas-peer-username"; - private static final String X_APPENGINE_GAIA_ID = "x-appengine-gaia-id"; - private static final String X_APPENGINE_GAIA_AUTHUSER = "x-appengine-gaia-authuser"; - private static final String X_APPENGINE_GAIA_SESSION = "x-appengine-gaia-session"; - private static final String X_APPENGINE_APPSERVER_DATACENTER = "x-appengine-appserver-datacenter"; - private static final String X_APPENGINE_APPSERVER_TASK_BNS = "x-appengine-appserver-task-bns"; - private static final String X_APPENGINE_DEFAULT_VERSION_HOSTNAME = - "x-appengine-default-version-hostname"; - private static final String X_APPENGINE_REQUEST_LOG_ID = "x-appengine-request-log-id"; - private static final String X_APPENGINE_QUEUENAME = "x-appengine-queuename"; - private static final String X_APPENGINE_TIMEOUT_MS = "x-appengine-timeout-ms"; - private static final String X_GOOGLE_INTERNAL_SKIPADMINCHECK = "x-google-internal-skipadmincheck"; - private static final String X_GOOGLE_INTERNAL_SKIPADMINCHECK_UC = - "X-Google-Internal-SkipAdminCheck"; - private static final String X_GOOGLE_INTERNAL_PROFILER = "x-google-internal-profiler"; - private static final String X_CLOUD_TRACE_CONTEXT = "x-cloud-trace-context"; - - private static final String IS_ADMIN_HEADER_VALUE = "1"; - private static final String IS_TRUSTED = "1"; - - // The impersonated IP address of warmup requests (and also background) - // () - private static final String WARMUP_IP = "0.1.0.3"; - - private static final ImmutableSet PRIVATE_APPENGINE_HEADERS = - ImmutableSet.of( - X_APPENGINE_API_TICKET, - X_APPENGINE_HTTPS, - X_APPENGINE_USER_IP, - X_APPENGINE_USER_EMAIL, - X_APPENGINE_AUTH_DOMAIN, - X_APPENGINE_USER_ID, - X_APPENGINE_USER_NICKNAME, - X_APPENGINE_USER_ORGANIZATION, - X_APPENGINE_USER_IS_ADMIN, - X_APPENGINE_TRUSTED_IP_REQUEST, - X_APPENGINE_LOAS_PEER_USERNAME, - X_APPENGINE_GAIA_ID, - X_APPENGINE_GAIA_AUTHUSER, - X_APPENGINE_GAIA_SESSION, - X_APPENGINE_APPSERVER_DATACENTER, - X_APPENGINE_APPSERVER_TASK_BNS, - X_APPENGINE_DEFAULT_VERSION_HOSTNAME, - X_APPENGINE_REQUEST_LOG_ID, - X_APPENGINE_TIMEOUT_MS, - X_GOOGLE_INTERNAL_PROFILER); + private final AppInfoFactory appInfoFactory; private final boolean passThroughPrivateHeaders; @@ -230,12 +200,12 @@ public final RuntimePb.UPRequest translateRequest(HttpServletRequest realRequest } } - if ("/_ah/background".equals(realRequest.getRequestURI())) { - if (WARMUP_IP.equals(httpRequest.getUserIp())) { + if (Objects.equals(realRequest.getRequestURI(), BACKGROUND_REQUEST_URL)) { + if (Objects.equals(httpRequest.getUserIp(), WARMUP_IP)) { upReqBuilder.setRequestType(UPRequest.RequestType.BACKGROUND); } - } else if ("/_ah/start".equals(realRequest.getRequestURI())) { - if (WARMUP_IP.equals(httpRequest.getUserIp())) { + } else if (Objects.equals(realRequest.getRequestURI(), WARMUP_REQUEST_URL)) { + if (Objects.equals(httpRequest.getUserIp(), WARMUP_IP)) { // This request came from within App Engine via secure internal channels; tell Jetty // it's HTTPS to avoid 403 because of web.xml security-constraint checks. httpRequest.setIsHttps(true); From 4530b978b3a3331363aebc098cc1b12859f3e586 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Fri, 28 Jun 2024 15:08:21 +1000 Subject: [PATCH 18/28] do not early start the AppEngineWebAppContext in HttpConnector mode Signed-off-by: Lachlan Roberts --- .../jetty9/JettyServletEngineAdapter.java | 73 +++++++++---------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyServletEngineAdapter.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyServletEngineAdapter.java index 2f1ab75b6..b52d0c968 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyServletEngineAdapter.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyServletEngineAdapter.java @@ -118,12 +118,12 @@ public void start(String serverInfo, ServletEngineAdapter.Config runtimeOptions) server.setHandler(appVersionHandlerMap); } - boolean startJettyHttpProxy = false; - if (runtimeOptions.useJettyHttpProxy()) { - AppInfoFactory appInfoFactory; - AppVersionKey appVersionKey; - /* The init actions are not done in the constructor as they are not used when testing */ - try { + try { + boolean startJettyHttpProxy = false; + if (runtimeOptions.useJettyHttpProxy()) { + AppInfoFactory appInfoFactory; + AppVersionKey appVersionKey; + /* The init actions are not done in the constructor as they are not used when testing */ String appRoot = runtimeOptions.applicationRoot(); String appPath = runtimeOptions.fixedApplicationPath(); appInfoFactory = new AppInfoFactory(System.getenv()); @@ -134,41 +134,38 @@ public void start(String serverInfo, ServletEngineAdapter.Config runtimeOptions) Objects.requireNonNull(runtimeOptions.evaluationRuntimeServerInterface()); evaluationRuntimeServerInterface.addAppVersion(context, appinfo); context.getResponse(); - appVersionKey = AppVersionKey.fromAppInfo(appinfo); - appVersionHandlerMap.getHandler(appVersionKey); - } catch (Exception e) { - throw new IllegalStateException(e); - } - if (Boolean.getBoolean(HTTP_CONNECTOR_MODE)) { - logger.atInfo().log("Using HTTP_CONNECTOR_MODE to bypass RPC"); - JettyHttpProxy.insertHandlers(server); - AppVersion appVersion = appVersionHandlerMap.getAppVersion(appVersionKey); - server.insertHandler(new JettyHttpHandler(runtimeOptions, appVersion, appVersionKey, appInfoFactory)); - ServerConnector connector = JettyHttpProxy.newConnector(server, runtimeOptions); - server.addConnector(connector); - } else { - server.setAttribute( - "com.google.apphosting.runtime.jetty9.appYaml", - appYaml.orElseGet(() -> JettyServletEngineAdapter.getAppYaml(runtimeOptions))); - // Delay start of JettyHttpProxy until after the main server and application is started. - startJettyHttpProxy = true; + + if (Boolean.getBoolean(HTTP_CONNECTOR_MODE)) { + logger.atInfo().log("Using HTTP_CONNECTOR_MODE to bypass RPC"); + appVersionKey = AppVersionKey.fromAppInfo(appinfo); + appVersionHandlerMap.getHandler(appVersionKey); + JettyHttpProxy.insertHandlers(server); + AppVersion appVersion = appVersionHandlerMap.getAppVersion(appVersionKey); + server.insertHandler(new JettyHttpHandler(runtimeOptions, appVersion, appVersionKey, appInfoFactory)); + ServerConnector connector = JettyHttpProxy.newConnector(server, runtimeOptions); + server.addConnector(connector); + } else { + server.setAttribute( + "com.google.apphosting.runtime.jetty9.appYaml", + appYaml.orElseGet(() -> JettyServletEngineAdapter.getAppYaml(runtimeOptions))); + // Delay start of JettyHttpProxy until after the main server and application is started. + startJettyHttpProxy = true; + } } - } - ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(JettyServletEngineAdapter.class.getClassLoader()); - try { - server.start(); - if (startJettyHttpProxy) { - JettyHttpProxy.startServer(runtimeOptions); + ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(JettyServletEngineAdapter.class.getClassLoader()); + try { + server.start(); + if (startJettyHttpProxy) { + JettyHttpProxy.startServer(runtimeOptions); + } } - } catch (Exception ex) { - // TODO: Should we have a wrapper exception for this - // type of thing in ServletEngineAdapter? - throw new RuntimeException(ex); - } - finally { - Thread.currentThread().setContextClassLoader(oldContextClassLoader); + finally { + Thread.currentThread().setContextClassLoader(oldContextClassLoader); + } + } catch (Exception e) { + throw new IllegalStateException(e); } } From 6508f742586269d9b2ab80bad05fce0f2747b565 Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Mon, 1 Jul 2024 01:48:17 -0700 Subject: [PATCH 19/28] Update dependencies for appengine_standard. PiperOrigin-RevId: 648285833 Change-Id: I3619050952915e9d85399e4ab7b4047ee584591b --- applications/proberapp/pom.xml | 2 +- pom.xml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/applications/proberapp/pom.xml b/applications/proberapp/pom.xml index dcf50f271..65f18eb8f 100644 --- a/applications/proberapp/pom.xml +++ b/applications/proberapp/pom.xml @@ -96,7 +96,7 @@ com.google.cloud google-cloud-datastore - 2.20.1 + 2.20.2 com.google.cloud diff --git a/pom.xml b/pom.xml index d3e340b02..9a292b45a 100644 --- a/pom.xml +++ b/pom.xml @@ -64,8 +64,8 @@ UTF-8 9.4.54.v20240208 12.0.10 - 1.64.0 - 4.1.110.Final + 1.65.0 + 4.1.111.Final 2.0.13 https://oss.sonatype.org/content/repositories/google-snapshots/ sonatype-nexus-snapshots @@ -745,7 +745,7 @@ com.google.truth truth - 1.4.2 + 1.4.3 test @@ -786,7 +786,7 @@ org.codehaus.mojo versions-maven-plugin - 2.16.2 + 2.17.0 file:///${session.executionRootDirectory}/maven-version-rules.xml false @@ -941,7 +941,7 @@ org.codehaus.mojo versions-maven-plugin - 2.16.2 + 2.17.0 From 45b1856bd45b216ef2d0267680f4e19a7e5ff3ae Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 1 Jul 2024 09:04:26 +0000 Subject: [PATCH 20/28] Update all non-major dependencies --- pom.xml | 2 +- sdk_assembly/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9a292b45a..ccb397d94 100644 --- a/pom.xml +++ b/pom.xml @@ -751,7 +751,7 @@ com.google.truth.extensions truth-java8-extension - 1.4.2 + 1.4.3 test diff --git a/sdk_assembly/pom.xml b/sdk_assembly/pom.xml index d75ae46ee..78c501f8d 100644 --- a/sdk_assembly/pom.xml +++ b/sdk_assembly/pom.xml @@ -81,7 +81,7 @@ maven-dependency-plugin - 3.7.0 + 3.7.1 unpack From d5db139a3b1d58c49327cb32a952e9ca26d32ba6 Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Tue, 2 Jul 2024 14:18:48 -0700 Subject: [PATCH 21/28] Control response size limit via a new system property ("appengine.ignore.responseSizeLimit") that can avoid the limit check. We keep the request size constraint as it is now. The test is done in the Java code, but other layers have their own limits that might be a little bit different (less restrictive?). Maybe a less informative error would be emitted down the road, but not via the Java runtime. PiperOrigin-RevId: 648841006 Change-Id: I38f085a5ec8142d8258726bc542e9b442b2aa54c --- .../init/AppEngineWebXmlInitialParse.java | 7 +- .../runtime/AppEngineConstants.java | 2 + .../jetty/JettyServletEngineAdapter.java | 20 +- .../jetty9/JettyServletEngineAdapter.java | 13 +- .../jetty9/JavaRuntimeViaHttpBase.java | 77 +++- .../runtime/jetty9/SizeLimitIgnoreTest.java | 370 ++++++++++++++++++ 6 files changed, 462 insertions(+), 27 deletions(-) create mode 100644 runtime/test/src/test/java/com/google/apphosting/runtime/jetty9/SizeLimitIgnoreTest.java diff --git a/appengine_init/src/main/java/com/google/appengine/init/AppEngineWebXmlInitialParse.java b/appengine_init/src/main/java/com/google/appengine/init/AppEngineWebXmlInitialParse.java index d9810320f..01e115d61 100644 --- a/appengine_init/src/main/java/com/google/appengine/init/AppEngineWebXmlInitialParse.java +++ b/appengine_init/src/main/java/com/google/appengine/init/AppEngineWebXmlInitialParse.java @@ -46,6 +46,7 @@ public final class AppEngineWebXmlInitialParse { /** a formatted build timestamp with pattern yyyy-MM-dd'T'HH:mm:ssXXX */ public static final String BUILD_TIMESTAMP; + private static final String BUILD_VERSION; private static final Properties BUILD_PROPERTIES = new Properties(); @@ -56,7 +57,7 @@ public final class AppEngineWebXmlInitialParse { "/com/google/appengine/init/build.properties")) { BUILD_PROPERTIES.load(inputStream); } catch (Exception ok) { - // File not there; that's fine, just continue. + // File not there; that's fine, just continue. } GIT_HASH = BUILD_PROPERTIES.getProperty("buildNumber", "unknown"); System.setProperty("appengine.git.hash", GIT_HASH); @@ -124,7 +125,9 @@ private void setAppEngineUseProperties(final XMLEventReader reader) throws XMLSt System.setProperty("appengine.use.HttpConnector", value); } else if (prop.equalsIgnoreCase("appengine.use.allheaders")) { System.setProperty("appengine.use.allheaders", value); - } + } else if (prop.equalsIgnoreCase("appengine.ignore.responseSizeLimit")) { + System.setProperty("appengine.ignore.responseSizeLimit", value); + } } } } diff --git a/runtime/impl/src/main/java/com/google/apphosting/runtime/AppEngineConstants.java b/runtime/impl/src/main/java/com/google/apphosting/runtime/AppEngineConstants.java index 95f5c0bb3..164ada8a2 100644 --- a/runtime/impl/src/main/java/com/google/apphosting/runtime/AppEngineConstants.java +++ b/runtime/impl/src/main/java/com/google/apphosting/runtime/AppEngineConstants.java @@ -115,5 +115,7 @@ public final class AppEngineConstants { public static final String HTTP_CONNECTOR_MODE = "appengine.use.HttpConnector"; + public static final String IGNORE_RESPONSE_SIZE_LIMIT = "appengine.ignore.responseSizeLimit"; + private AppEngineConstants() {} } diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java index ff135be9b..e35b57770 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java @@ -16,6 +16,7 @@ package com.google.apphosting.runtime.jetty; import static com.google.apphosting.runtime.AppEngineConstants.HTTP_CONNECTOR_MODE; +import static com.google.apphosting.runtime.AppEngineConstants.IGNORE_RESPONSE_SIZE_LIMIT; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.apphosting.api.ApiProxy; @@ -26,7 +27,6 @@ import com.google.apphosting.base.protos.RuntimePb.UPResponse; import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.AppVersion; -import com.google.apphosting.runtime.AppEngineConstants; import com.google.apphosting.runtime.MutableUpResponse; import com.google.apphosting.runtime.ServletEngineAdapter; import com.google.apphosting.runtime.anyrpc.EvaluationRuntimeServerInterface; @@ -56,7 +56,6 @@ /** * This is an implementation of ServletEngineAdapter that uses the third-party Jetty servlet engine. - * */ public class JettyServletEngineAdapter implements ServletEngineAdapter { private static final GoogleLogger logger = GoogleLogger.forEnclosingClass(); @@ -94,7 +93,8 @@ private static AppYaml getAppYaml(ServletEngineAdapter.Config runtimeOptions) { try { appYaml = AppYaml.parse(new InputStreamReader(new FileInputStream(appYamlFile), UTF_8)); } catch (FileNotFoundException | AppEngineConfigException e) { - logger.atWarning().log("Failed to load app.yaml file at location %s - %s", + logger.atWarning().log( + "Failed to load app.yaml file at location %s - %s", appYamlFile.getPath(), e.getMessage()); } return appYaml; @@ -143,9 +143,10 @@ public void run(Runnable runnable) { } }; server.addConnector(rpcConnector); - AppVersionHandlerFactory appVersionHandlerFactory = AppVersionHandlerFactory.newInstance(server, serverInfo); + AppVersionHandlerFactory appVersionHandlerFactory = + AppVersionHandlerFactory.newInstance(server, serverInfo); appVersionHandler = new AppVersionHandler(appVersionHandlerFactory); - if (!"java8".equals(System.getenv("GAE_RUNTIME"))) { + if (!Boolean.getBoolean(IGNORE_RESPONSE_SIZE_LIMIT)) { CoreSizeLimitHandler sizeLimitHandler = new CoreSizeLimitHandler(-1, MAX_RESPONSE_SIZE); sizeLimitHandler.setHandler(appVersionHandler); server.setHandler(sizeLimitHandler); @@ -223,7 +224,8 @@ public void deleteAppVersion(AppVersion appVersion) { /** * Sets the {@link com.google.apphosting.runtime.SessionStoreFactory} that will be used to create * the list of {@link com.google.apphosting.runtime.SessionStore SessionStores} to which the HTTP - * Session will be stored, if sessions are enabled. This method must be invoked after {@link #start(String, Config)}. + * Session will be stored, if sessions are enabled. This method must be invoked after {@link + * #start(String, Config)}. */ @Override public void setSessionStoreFactory(com.google.apphosting.runtime.SessionStoreFactory factory) { @@ -242,15 +244,15 @@ public void serviceRequest(UPRequest upRequest, MutableUpResponse upResponse) th AppVersionKey appVersionKey = AppVersionKey.fromUpRequest(upRequest); AppVersionKey lastVersionKey = lastAppVersionKey; if (lastVersionKey != null) { - // We already have created the handler on the previous request, so no need to do another getHandler(). + // We already have created the handler on the previous request, so no need to do another + // getHandler(). // The two AppVersionKeys must be the same as we only support one app version. if (!Objects.equals(appVersionKey, lastVersionKey)) { upResponse.setError(UPResponse.ERROR.UNKNOWN_APP_VALUE); upResponse.setErrorMessage("Unknown app: " + appVersionKey); return; } - } - else { + } else { if (!appVersionHandler.ensureHandler(appVersionKey)) { upResponse.setError(UPResponse.ERROR.UNKNOWN_APP_VALUE); upResponse.setErrorMessage("Unknown app: " + appVersionKey); diff --git a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyServletEngineAdapter.java b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyServletEngineAdapter.java index b1b205310..6e7ed15de 100644 --- a/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyServletEngineAdapter.java +++ b/runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyServletEngineAdapter.java @@ -16,6 +16,7 @@ package com.google.apphosting.runtime.jetty9; +import static com.google.apphosting.runtime.AppEngineConstants.IGNORE_RESPONSE_SIZE_LIMIT; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.apphosting.base.AppVersionKey; @@ -25,6 +26,7 @@ import com.google.apphosting.runtime.AppVersion; import com.google.apphosting.runtime.MutableUpResponse; import com.google.apphosting.runtime.ServletEngineAdapter; +import com.google.apphosting.runtime.SessionStoreFactory; import com.google.apphosting.utils.config.AppEngineConfigException; import com.google.apphosting.utils.config.AppYaml; import com.google.common.flogger.GoogleLogger; @@ -43,7 +45,6 @@ /** * This is an implementation of ServletEngineAdapter that uses the third-party Jetty servlet engine. - * */ public class JettyServletEngineAdapter implements ServletEngineAdapter { private static final GoogleLogger logger = GoogleLogger.forEnclosingClass(); @@ -89,7 +90,8 @@ private static AppYaml getAppYaml(ServletEngineAdapter.Config runtimeOptions) { try { appYaml = AppYaml.parse(new InputStreamReader(new FileInputStream(appYamlFile), UTF_8)); } catch (FileNotFoundException | AppEngineConfigException e) { - logger.atWarning().log("Failed to load app.yaml file at location %s - %s", + logger.atWarning().log( + "Failed to load app.yaml file at location %s - %s", appYamlFile.getPath(), e.getMessage()); } return appYaml; @@ -102,10 +104,11 @@ public void start(String serverInfo, ServletEngineAdapter.Config runtimeOptions) server.setConnectors(new Connector[] {rpcConnector}); AppVersionHandlerFactory appVersionHandlerFactory = new AppVersionHandlerFactory( - server, serverInfo, contextFactory, /*useJettyErrorPageHandler=*/ false); + server, serverInfo, contextFactory, /* useJettyErrorPageHandler= */ false); appVersionHandlerMap = new AppVersionHandlerMap(appVersionHandlerFactory); - if (!"java8".equals(System.getenv("GAE_RUNTIME"))) { + if (!Objects.equals(System.getenv("GAE_RUNTIME"), "java8") + && !Boolean.getBoolean(IGNORE_RESPONSE_SIZE_LIMIT)) { SizeLimitHandler sizeLimitHandler = new SizeLimitHandler(-1, MAX_RESPONSE_SIZE); sizeLimitHandler.setHandler(appVersionHandlerMap); server.setHandler(sizeLimitHandler); @@ -155,7 +158,7 @@ public void deleteAppVersion(AppVersion appVersion) { * #start(String)}. */ @Override - public void setSessionStoreFactory(com.google.apphosting.runtime.SessionStoreFactory factory) { + public void setSessionStoreFactory(SessionStoreFactory factory) { appVersionHandlerMap.setSessionStoreFactory(factory); } diff --git a/runtime/test/src/test/java/com/google/apphosting/runtime/jetty9/JavaRuntimeViaHttpBase.java b/runtime/test/src/test/java/com/google/apphosting/runtime/jetty9/JavaRuntimeViaHttpBase.java index 03903e6ea..979a9c213 100644 --- a/runtime/test/src/test/java/com/google/apphosting/runtime/jetty9/JavaRuntimeViaHttpBase.java +++ b/runtime/test/src/test/java/com/google/apphosting/runtime/jetty9/JavaRuntimeViaHttpBase.java @@ -42,6 +42,7 @@ import com.google.common.reflect.ClassPath; import com.google.common.reflect.ClassPath.ResourceInfo; import com.google.common.reflect.Reflection; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.ForOverride; import com.google.appengine.repackaged.com.google.protobuf.ByteString; import com.google.appengine.repackaged.com.google.protobuf.ExtensionRegistry; @@ -84,10 +85,12 @@ public abstract class JavaRuntimeViaHttpBase { @ClassRule public static TemporaryFolder temporaryFolder = new TemporaryFolder(); private static final String RUNTIME_LOCATION_ROOT = "java/com/google/apphosting"; static final int RESPONSE_200 = 200; + @FunctionalInterface interface ApiServerFactory { ApiServerT newApiServer(int apiPort, int runtimePort) throws IOException; } + static class RuntimeContext implements AutoCloseable { private final Process runtimeProcess; private final ApiServerT httpApiServer; @@ -95,6 +98,7 @@ static class RuntimeContext implements AutoCloseab private final int jettyPort; private final OutputPump outPump; private final OutputPump errPump; + private RuntimeContext( Process runtimeProcess, ApiServerT httpApiServer, @@ -109,14 +113,19 @@ private RuntimeContext( this.outPump = outPump; this.errPump = errPump; } + public int getPort() { return jettyPort; } + @AutoValue abstract static class Config { abstract ImmutableMap environmentEntries(); + abstract ImmutableList launcherFlags(); + abstract ApiServerFactory apiServerFactory(); + // The default configuration uses an API server that rejects all API calls as unknown. // Individual tests can configure a different server, including the HttpApiServer from the SDK // which provides APIs using their dev app server implementations. @@ -125,35 +134,42 @@ static Builder builder() { (apiPort, runtimePort) -> DummyApiServer.create(apiPort, ImmutableMap.of()); return builder(apiServerFactory); } + static Builder builder( ApiServerFactory apiServerFactory) { return new AutoValue_JavaRuntimeViaHttpBase_RuntimeContext_Config.Builder() .setEnvironmentEntries(ImmutableMap.of()) .setApiServerFactory(apiServerFactory); } + @AutoValue.Builder abstract static class Builder { private boolean applicationPath; private boolean applicationRoot; + /** * Sets the application path. In this approach, applicationPath is the complete application * location. */ + @CanIgnoreReturnValue Builder setApplicationPath(String path) { applicationPath = true; launcherFlagsBuilder().add("--fixed_application_path=" + path); return this; } + /** Sets Jetty's max request header size. */ Builder setJettyRequestHeaderSize(int size) { launcherFlagsBuilder().add("--jetty_request_header_size=" + size); return this; } + /** Sets Jetty's max response header size. */ Builder setJettyResponseHeaderSize(int size) { launcherFlagsBuilder().add("--jetty_response_header_size=" + size); return this; } + /** * Sets the application root. In this legacy case, you need to set the correct set of env * variables for "GAE_APPLICATION", "GAE_VERSION", "GAE_DEPLOYMENT_ID" with a correct @@ -168,10 +184,15 @@ Builder setApplicationRoot(String root) { launcherFlagsBuilder().add("--application_root=" + root); return this; } + abstract Builder setEnvironmentEntries(ImmutableMap entries); + abstract ImmutableList.Builder launcherFlagsBuilder(); + abstract Builder setApiServerFactory(ApiServerFactory factory); + abstract Config autoBuild(); + Config build() { if (applicationPath == applicationRoot) { throw new IllegalStateException( @@ -181,6 +202,7 @@ Config build() { } } } + /** JVM flags needed for JDK above JDK8 */ private static ImmutableList optionalFlags() { if (!JAVA_VERSION.value().startsWith("1.8")) { @@ -197,6 +219,7 @@ private static ImmutableList optionalFlags() { } return ImmutableList.of("-showversion"); // Just so that the list is not empty. } + static RuntimeContext create( Config config) throws IOException, InterruptedException { PortPicker portPicker = PortPicker.create(); @@ -212,11 +235,11 @@ static RuntimeContext create( .isTrue(); InetSocketAddress apiSocketAddress = new InetSocketAddress(apiPort); ImmutableList.Builder builder = ImmutableList.builder(); - builder.add(JAVA_HOME.value() + "/bin/java"); - Integer debugPort = Integer.getInteger("appengine.debug.port"); - if (debugPort != null) { + builder.add(JAVA_HOME.value() + "/bin/java"); + Integer debugPort = Integer.getInteger("appengine.debug.port"); + if (debugPort != null) { builder.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:" + debugPort); - } + } ImmutableList runtimeArgs = builder .add( @@ -225,6 +248,8 @@ static RuntimeContext create( "-Dappengine.use.EE10=" + Boolean.getBoolean("appengine.use.EE10"), "-Dappengine.use.HttpConnector=" + Boolean.getBoolean("appengine.use.HttpConnector"), + "-Dappengine.ignore.responseSizeLimit=" + + Boolean.getBoolean("appengine.ignore.responseSizeLimit"), "-Djetty.server.dumpAfterStart=" + Boolean.getBoolean("jetty.server.dumpAfterStart"), "-Duse.mavenjars=" + useMavenJars(), @@ -262,35 +287,41 @@ static RuntimeContext create( return new RuntimeContext<>( runtimeProcess, httpApiServer, httpClient, jettyPort, outPump, errPump); } + public static boolean isPortAvailable(String host, int port) { - try { - Socket socket = new Socket(host, port); - socket.close(); - return true; - } catch (Exception e) { - return false; - } + try { + try (Socket socket = new Socket(host, port)) {} + return true; + } catch (Exception e) { + return false; + } } + private static List jvmFlagsFromEnvironment(ImmutableMap env) { return Splitter.on(' ').omitEmptyStrings().splitToList(env.getOrDefault("GAE_JAVA_OPTS", "")); } + ApiServerT getApiServer() { return httpApiServer; } + HttpClient getHttpClient() { return httpClient; } + String jettyUrl(String urlPath) { return String.format( "http://%s%s", HostAndPort.fromParts(new InetSocketAddress(jettyPort).getHostString(), jettyPort), urlPath); } + void executeHttpGet(String url, String expectedResponseBody, int expectedReturnCode) throws Exception { executeHttpGetWithRetries( url, expectedResponseBody, expectedReturnCode, /* numberOfRetries= */ 1); } + String executeHttpGet(String urlPath, int expectedReturnCode) throws Exception { HttpGet get = new HttpGet(jettyUrl(urlPath)); HttpResponse response = httpClient.execute(get); @@ -306,6 +337,7 @@ String executeHttpGet(String urlPath, int expectedReturnCode) throws Exception { EntityUtils.consumeQuietly(entity); } } + void executeHttpGetWithRetries( String urlPath, String expectedResponse, int expectedReturnCode, int numberOfRetries) throws Exception { @@ -324,12 +356,15 @@ void executeHttpGetWithRetries( assertThat(content).isEqualTo(expectedResponse); assertThat(retCode).isEqualTo(expectedReturnCode); } + void awaitStdoutLineMatching(String pattern, long timeoutSeconds) throws InterruptedException { outPump.awaitOutputLineMatching(pattern, timeoutSeconds); } + void awaitStderrLineMatching(String pattern, long timeoutSeconds) throws InterruptedException { errPump.awaitOutputLineMatching(pattern, timeoutSeconds); } + private static Process launchRuntime( ImmutableList args, ImmutableMap environmentEntries) throws IOException { @@ -337,29 +372,36 @@ private static Process launchRuntime( pb.environment().putAll(environmentEntries); return pb.start(); } + Process runtimeProcess() { return runtimeProcess; } + @Override public void close() throws IOException { runtimeProcess.destroy(); httpApiServer.close(); } } + static boolean useMavenJars() { return Boolean.getBoolean("use.mavenjars"); } + static boolean useJetty94LegacyMode() { return Boolean.getBoolean("com.google.apphosting.runtime.jetty94.LEGACY_MODE"); } + static class OutputPump implements Runnable { private final BufferedReader stream; private final String echoPrefix; private final BlockingQueue outputQueue = new LinkedBlockingQueue<>(); + OutputPump(InputStream instream, String echoPrefix) { this.stream = new BufferedReader(new InputStreamReader(instream, UTF_8)); this.echoPrefix = echoPrefix; } + @Override public void run() { String line; @@ -372,6 +414,7 @@ public void run() { throw new RuntimeException(e); } } + void awaitOutputLineMatching(String pattern, long timeoutSeconds) throws InterruptedException { long timeoutMillis = MILLISECONDS.convert(timeoutSeconds, SECONDS); long deadline = System.currentTimeMillis() + timeoutMillis; @@ -387,8 +430,10 @@ void awaitOutputLineMatching(String pattern, long timeoutSeconds) throws Interru } } } + private static final Pattern JAR_URL_PATTERN = Pattern.compile("jar:file:(.*)!(.*)"); private static final Pattern JAR_FILE_URL_PATTERN = Pattern.compile("file:(.*\\.jar)"); + /** * Extract the test app with the given name into the given output directory. The situation is that * we have a jar file in our classpath that contains this app, plus maybe a bunch of other stuff. @@ -448,6 +493,7 @@ static void copyAppToDir(String appName, Path dir) throws IOException { } } } + private static void copyJarContainingClass(String className, Path toPath) throws IOException { try { Class threadManager = Class.forName(className); @@ -469,6 +515,7 @@ private static void copyJarContainingClass(String className, Path toPath) throws // OK: the app presumably doesn't need this. } } + /** * An API server that handles API calls via the supplied handler map. Each incoming API call is * looked up as {@code service.method}, for example {@code urlfetch.Fetch}, to discover a @@ -480,11 +527,13 @@ private static void copyJarContainingClass(String className, Path toPath) throws */ static class DummyApiServer implements Closeable { private static final GoogleLogger logger = GoogleLogger.forEnclosingClass(); + static DummyApiServer create( int apiPort, ImmutableMap> handlerMap) throws IOException { return create(apiPort, handlerMap, request -> {}); } + static DummyApiServer create( int apiPort, ImmutableMap> handlerMap, @@ -498,13 +547,16 @@ static DummyApiServer create( httpServer.start(); return apiServer; } + private final HttpServer httpServer; private final Function> handlerLookup; private final Consumer requestObserver; + DummyApiServer( HttpServer httpServer, Function> handlerLookup) { this(httpServer, handlerLookup, request -> {}); } + private DummyApiServer( HttpServer httpServer, Function> handlerLookup, @@ -513,14 +565,17 @@ private DummyApiServer( this.handlerLookup = handlerLookup; this.requestObserver = requestObserver; } + @Override public void close() { httpServer.stop(0); } + @ForOverride RemoteApiPb.Response.Builder newResponseBuilder() { return RemoteApiPb.Response.newBuilder(); } + void handle(HttpExchange exchange) throws IOException { try (InputStream in = exchange.getRequestBody(); OutputStream out = exchange.getResponseBody()) { diff --git a/runtime/test/src/test/java/com/google/apphosting/runtime/jetty9/SizeLimitIgnoreTest.java b/runtime/test/src/test/java/com/google/apphosting/runtime/jetty9/SizeLimitIgnoreTest.java new file mode 100644 index 000000000..d02973cda --- /dev/null +++ b/runtime/test/src/test/java/com/google/apphosting/runtime/jetty9/SizeLimitIgnoreTest.java @@ -0,0 +1,370 @@ +/* + * Copyright 2021 Google LLC + * + * 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 + * + * https://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.apphosting.runtime.jetty9; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.lessThan; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; +import java.util.zip.GZIPOutputStream; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentProvider; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Response; +import org.eclipse.jetty.client.api.Result; +import org.eclipse.jetty.client.util.ByteBufferContentProvider; +import org.eclipse.jetty.client.util.DeferredContentProvider; +import org.eclipse.jetty.client.util.InputStreamContentProvider; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.util.Utf8StringBuilder; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class SizeLimitIgnoreTest extends JavaRuntimeViaHttpBase { + @Parameterized.Parameters + public static List data() { + return Arrays.asList( + new Object[][] { + {"jetty94", false}, + {"ee8", false}, + {"ee10", false}, + {"ee8", true}, + {"ee10", true}, + }); + } + + private static final int MAX_SIZE = 32 * 1024 * 1024; + @Rule public TemporaryFolder temp = new TemporaryFolder(); + private final HttpClient httpClient = new HttpClient(); + private final boolean httpMode; + private final String environment; + private RuntimeContext runtime; + + public SizeLimitIgnoreTest(String environment, boolean httpMode) { + this.environment = environment; + this.httpMode = httpMode; + System.setProperty("appengine.use.HttpConnector", Boolean.toString(httpMode)); + System.setProperty("appengine.ignore.responseSizeLimit", "true"); + } + + @Before + public void before() throws Exception { + String app = "sizelimit" + environment; + copyAppToDir(app, temp.getRoot().toPath()); + httpClient.start(); + runtime = runtimeContext(); + assertEnvironment(); + System.err.println("==== Using Environment: " + environment + " " + httpMode + " ===="); + } + + @After + public void after() throws Exception { + httpClient.stop(); + runtime.close(); + } + + @Test + public void testResponseContentBelowMaxLength() throws Exception { + long contentLength = MAX_SIZE; + String url = runtime.jettyUrl("/?size=" + contentLength); + CompletableFuture completionListener = new CompletableFuture<>(); + AtomicLong contentReceived = new AtomicLong(); + httpClient + .newRequest(url) + .onResponseContentAsync( + (response, content, callback) -> { + contentReceived.addAndGet(content.remaining()); + callback.succeeded(); + }) + .header("setCustomHeader", "true") + .send(completionListener::complete); + + Result result = completionListener.get(5, TimeUnit.SECONDS); + assertThat(result.getResponse().getStatus(), equalTo(HttpStatus.OK_200)); + assertThat(contentReceived.get(), equalTo(contentLength)); + assertThat(result.getResponse().getHeaders().get("custom-header"), equalTo("true")); + } + + @Test + public void testResponseContentAboveMaxLength() throws Exception { + long contentLength = MAX_SIZE + 1; + String url = runtime.jettyUrl("/?size=" + contentLength); + CompletableFuture completionListener = new CompletableFuture<>(); + AtomicLong contentReceived = new AtomicLong(); + httpClient + .newRequest(url) + .onResponseContentAsync( + (response, content, callback) -> { + contentReceived.addAndGet(content.remaining()); + callback.succeeded(); + }) + .header("setCustomHeader", "true") + .send(completionListener::complete); + + Result result = completionListener.get(5, TimeUnit.SECONDS); + assertThat(result.getResponse().getStatus(), equalTo(HttpStatus.OK_200)); + assertThat(contentReceived.get(), equalTo(contentLength)); + assertThat(result.getResponse().getHeaders().get("custom-header"), equalTo("true")); + } + + @Test + public void testResponseContentBelowMaxLengthGzip() throws Exception { + long contentLength = MAX_SIZE; + String url = runtime.jettyUrl("/?size=" + contentLength); + CompletableFuture completionListener = new CompletableFuture<>(); + AtomicLong contentReceived = new AtomicLong(); + httpClient.getContentDecoderFactories().clear(); + httpClient + .newRequest(url) + .onResponseContentAsync( + (response, content, callback) -> { + contentReceived.addAndGet(content.remaining()); + callback.succeeded(); + }) + .header(HttpHeader.ACCEPT_ENCODING, "gzip") + .send(completionListener::complete); + + Result result = completionListener.get(5, TimeUnit.SECONDS); + assertThat(result.getResponse().getHeaders().get(HttpHeader.CONTENT_ENCODING), equalTo("gzip")); + assertThat(result.getResponse().getStatus(), equalTo(HttpStatus.OK_200)); + assertThat(contentReceived.get(), lessThan(contentLength)); + } + + @Test + public void testResponseContentAboveMaxLengthGzip() throws Exception { + long contentLength = MAX_SIZE + 1; + String url = runtime.jettyUrl("/?size=" + contentLength); + CompletableFuture completionListener = new CompletableFuture<>(); + AtomicLong contentReceived = new AtomicLong(); + httpClient.getContentDecoderFactories().clear(); + httpClient + .newRequest(url) + .onResponseContentAsync( + (response, content, callback) -> { + contentReceived.addAndGet(content.remaining()); + callback.succeeded(); + }) + .header(HttpHeader.ACCEPT_ENCODING, "gzip") + .send(completionListener::complete); + + Result result = completionListener.get(5, TimeUnit.SECONDS); + assertThat(result.getResponse().getHeaders().get(HttpHeader.CONTENT_ENCODING), equalTo("gzip")); + assertThat(result.getResponse().getStatus(), equalTo(HttpStatus.OK_200)); + assertThat(contentReceived.get(), lessThan(contentLength)); + } + + @Test + public void testRequestContentBelowMaxLength() throws Exception { + int contentLength = MAX_SIZE; + + byte[] data = new byte[contentLength]; + Arrays.fill(data, (byte) 'X'); + ContentProvider content = new ByteBufferContentProvider(BufferUtil.toBuffer(data)); + String url = runtime.jettyUrl("/"); + ContentResponse response = httpClient.newRequest(url).content(content).send(); + + assertThat(response.getStatus(), equalTo(HttpStatus.OK_200)); + assertThat( + response.getContentAsString(), containsString("RequestContentLength: " + contentLength)); + } + + @Test + public void testRequestContentAboveMaxLength() throws Exception { + int contentLength = MAX_SIZE + 1; + + CompletableFuture completionListener = new CompletableFuture<>(); + byte[] data = new byte[contentLength]; + Arrays.fill(data, (byte) 'X'); + Utf8StringBuilder received = new Utf8StringBuilder(); + ContentProvider content = new ByteBufferContentProvider(BufferUtil.toBuffer(data)); + String url = runtime.jettyUrl("/"); + httpClient + .newRequest(url) + .content(content) + .onResponseContentAsync( + (response, content1, callback) -> { + received.append(content1); + callback.succeeded(); + }) + .send(completionListener::complete); + + Result result = completionListener.get(5, TimeUnit.SECONDS); + assertThat(result.getResponse().getStatus(), equalTo(HttpStatus.PAYLOAD_TOO_LARGE_413)); + + // If there is no Content-Length header the SizeLimitHandler fails the response as well. + if (result.getResponseFailure() == null) { + assertThat(received.toString(), containsString("Request body is too large")); + } + } + + @Test + public void testRequestContentBelowMaxLengthGzip() throws Exception { + int contentLength = MAX_SIZE; + + CompletableFuture completionListener = new CompletableFuture<>(); + byte[] data = new byte[contentLength]; + Arrays.fill(data, (byte) 'X'); + Utf8StringBuilder received = new Utf8StringBuilder(); + ContentProvider content = new InputStreamContentProvider(gzip(data)); + + String url = runtime.jettyUrl("/"); + httpClient + .newRequest(url) + .content(content) + .onResponseContentAsync( + (response, content1, callback) -> { + received.append(content1); + callback.succeeded(); + }) + .header(HttpHeader.CONTENT_ENCODING, "gzip") + .send(completionListener::complete); + + Result result = completionListener.get(5, TimeUnit.SECONDS); + assertThat(result.getResponse().getStatus(), equalTo(HttpStatus.OK_200)); + assertThat(received.toString(), containsString("RequestContentLength: " + contentLength)); + } + + @Test + public void testRequestContentAboveMaxLengthGzip() throws Exception { + int contentLength = MAX_SIZE + 1; + + CompletableFuture completionListener = new CompletableFuture<>(); + byte[] data = new byte[contentLength]; + Arrays.fill(data, (byte) 'X'); + Utf8StringBuilder received = new Utf8StringBuilder(); + ContentProvider content = new InputStreamContentProvider(gzip(data)); + + String url = runtime.jettyUrl("/"); + httpClient + .newRequest(url) + .content(content) + .onResponseContentAsync( + (response, content1, callback) -> { + received.append(content1); + callback.succeeded(); + }) + .header(HttpHeader.CONTENT_ENCODING, "gzip") + .send(completionListener::complete); + + Result result = completionListener.get(5, TimeUnit.SECONDS); + assertThat(result.getResponse().getStatus(), equalTo(HttpStatus.PAYLOAD_TOO_LARGE_413)); + + // If there is no Content-Length header the SizeLimitHandler fails the response as well. + if (result.getResponseFailure() == null) { + assertThat(received.toString(), containsString("Request body is too large")); + } + } + + @Test + public void testResponseContentLengthHeader() throws Exception { + long contentLength = MAX_SIZE + 1; + String url = runtime.jettyUrl("/?setContentLength=" + contentLength); + httpClient.getContentDecoderFactories().clear(); + ContentResponse response = httpClient.newRequest(url).send(); + + assertThat(response.getStatus(), equalTo(HttpStatus.INTERNAL_SERVER_ERROR_500)); + + // No content is sent on the Jetty 9.4 runtime. + if (!Objects.equals(environment, "jetty94")) { + assertThat(response.getContentAsString(), containsString("IllegalStateException")); + } + } + + @Test + public void testRequestContentLengthHeader() throws Exception { + CompletableFuture completionListener = new CompletableFuture<>(); + DeferredContentProvider provider = new DeferredContentProvider(ByteBuffer.allocate(1)); + int contentLength = MAX_SIZE + 1; + String url = runtime.jettyUrl("/"); + Utf8StringBuilder received = new Utf8StringBuilder(); + httpClient + .newRequest(url) + .header(HttpHeader.CONTENT_LENGTH, Long.toString(contentLength)) + .header("foo", "bar") + .content(provider) + .onResponseContentAsync( + (response, content, callback) -> { + received.append(content); + callback.succeeded(); + provider.close(); + }) + .send(completionListener::complete); + + Result result = completionListener.get(5, TimeUnit.SECONDS); + Response response = result.getResponse(); + assertThat(response.getStatus(), equalTo(HttpStatus.PAYLOAD_TOO_LARGE_413)); + + // If there is no Content-Length header the SizeLimitHandler fails the response as well. + if (result.getResponseFailure() == null) { + assertThat(received.toString(), containsString("Request body is too large")); + } + } + + private RuntimeContext runtimeContext() throws Exception { + RuntimeContext.Config config = + RuntimeContext.Config.builder().setApplicationPath(temp.getRoot().toString()).build(); + return RuntimeContext.create(config); + } + + private void assertEnvironment() throws Exception { + String match; + switch (environment) { + case "jetty94": + match = "org.eclipse.jetty.server.Request"; + break; + case "ee8": + match = "org.eclipse.jetty.ee8"; + break; + case "ee10": + match = "org.eclipse.jetty.ee10"; + break; + default: + throw new IllegalArgumentException(environment); + } + + String runtimeUrl = runtime.jettyUrl("/?getRequestClass=true"); + ContentResponse response = httpClient.GET(runtimeUrl); + assertThat(response.getContentAsString(), containsString(match)); + } + + private static InputStream gzip(byte[] data) throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream)) { + gzipOutputStream.write(data); + } + return new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); + } +} From 7dce20b05de181af6ccc04e5a44f3425a52b71fe Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Wed, 3 Jul 2024 19:25:05 +1000 Subject: [PATCH 22/28] Issue #241 - fix deferred authentication for Java21 EE10 runtime Signed-off-by: Lachlan Roberts --- .../runtime/jetty/EE10AppEngineAuthentication.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shared_sdk_jetty12/src/main/java/com/google/apphosting/runtime/jetty/EE10AppEngineAuthentication.java b/shared_sdk_jetty12/src/main/java/com/google/apphosting/runtime/jetty/EE10AppEngineAuthentication.java index f502ba770..7e66d1495 100644 --- a/shared_sdk_jetty12/src/main/java/com/google/apphosting/runtime/jetty/EE10AppEngineAuthentication.java +++ b/shared_sdk_jetty12/src/main/java/com/google/apphosting/runtime/jetty/EE10AppEngineAuthentication.java @@ -179,10 +179,6 @@ public AuthenticationState validateRequest(Request req, Response res, Callback c throw new ServerAuthException("validateRequest called with null response!!!"); } - if (AuthenticationState.Deferred.isDeferred(res)) { - return null; - } - try { UserService userService = UserServiceFactory.getUserService(); // If the user is authenticated already, just create a @@ -195,6 +191,10 @@ public AuthenticationState validateRequest(Request req, Response res, Callback c } } + if (AuthenticationState.Deferred.isDeferred(res)) { + return null; + } + try { logger.atFine().log( "Got %s but no one was logged in, redirecting.", request.getRequestURI()); From cd0a6ea1f2b6592aa50a47590c47e8382122f1c2 Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Fri, 5 Jul 2024 03:01:24 -0700 Subject: [PATCH 23/28] Fix a build break in the Jetty 12 runtime happening only on github. PiperOrigin-RevId: 649598224 Change-Id: I0d4a8d0e64d5d76d9d3951077d4df3a6bd2f6164 --- .../apphosting/runtime/jetty/JettyServletEngineAdapter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java index 2cdcb1c92..a71a85a2a 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java @@ -35,7 +35,6 @@ import com.google.apphosting.runtime.jetty.delegate.impl.DelegateRpcExchange; import com.google.apphosting.runtime.jetty.http.JettyHttpHandler; import com.google.apphosting.runtime.jetty.proxy.JettyHttpProxy; -import com.google.apphosting.runtime.jetty9.AppVersionHandlerFactory; import com.google.apphosting.utils.config.AppEngineConfigException; import com.google.apphosting.utils.config.AppYaml; import com.google.common.flogger.GoogleLogger; From ec6171a71f6d8293ef07f7d056a2573e6e7f5e7c Mon Sep 17 00:00:00 2001 From: Ludovic Champenois Date: Fri, 5 Jul 2024 08:06:02 -0700 Subject: [PATCH 24/28] Fix build issue introduced via a google internal change refactoring in EE8AppVersionHandlerFactory.java PiperOrigin-RevId: 649653884 Change-Id: Ieaf14a85e52724182049a26862f2f0a0d98398e6 --- .../runtime/jetty/ee8/EE8AppVersionHandlerFactory.java | 1 - .../google/apphosting/runtime/jetty/proxy/JettyHttpProxy.java | 1 - 2 files changed, 2 deletions(-) diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/EE8AppVersionHandlerFactory.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/EE8AppVersionHandlerFactory.java index 7cf1bcd55..e3de458dd 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/EE8AppVersionHandlerFactory.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/ee8/EE8AppVersionHandlerFactory.java @@ -24,7 +24,6 @@ import com.google.apphosting.runtime.SessionsConfig; import com.google.apphosting.runtime.jetty.AppVersionHandlerFactory; import com.google.apphosting.runtime.jetty.SessionManagerHandler; -import com.google.apphosting.runtime.jetty9.AppEngineWebAppContext; import com.google.common.flogger.GoogleLogger; import com.google.common.html.HtmlEscapers; import java.io.File; diff --git a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/JettyHttpProxy.java b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/JettyHttpProxy.java index 9edb52bb4..f8f030817 100644 --- a/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/JettyHttpProxy.java +++ b/runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/proxy/JettyHttpProxy.java @@ -26,7 +26,6 @@ import com.google.apphosting.runtime.jetty.AppInfoFactory; import com.google.apphosting.runtime.jetty.CoreSizeLimitHandler; import com.google.apphosting.runtime.jetty.JettyServletEngineAdapter; -import com.google.apphosting.runtime.jetty9.JettyServerConnectorWithReusePort; import com.google.common.base.Ascii; import com.google.common.base.Throwables; import com.google.common.flogger.GoogleLogger; From 352aa4f06f433499924eacb40c2ee95858788488 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 8 Jul 2024 00:25:32 +0000 Subject: [PATCH 25/28] Update all non-major dependencies --- appengine_setup/testapps/jetty12_testapp/pom.xml | 2 +- applications/proberapp/pom.xml | 2 +- pom.xml | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/appengine_setup/testapps/jetty12_testapp/pom.xml b/appengine_setup/testapps/jetty12_testapp/pom.xml index 2c250e2f5..8ac7671c5 100644 --- a/appengine_setup/testapps/jetty12_testapp/pom.xml +++ b/appengine_setup/testapps/jetty12_testapp/pom.xml @@ -26,7 +26,7 @@ com.google.appengine.setup.testapps jetty12_testapp - 12.0.10 + 12.0.11 1.9.22.1 diff --git a/applications/proberapp/pom.xml b/applications/proberapp/pom.xml index 65f18eb8f..59488bfe5 100644 --- a/applications/proberapp/pom.xml +++ b/applications/proberapp/pom.xml @@ -58,7 +58,7 @@ com.google.cloud google-cloud-spanner - 6.70.0 + 6.71.0 com.google.api diff --git a/pom.xml b/pom.xml index ccb397d94..1023eb375 100644 --- a/pom.xml +++ b/pom.xml @@ -62,8 +62,8 @@ 1.8 1.8 UTF-8 - 9.4.54.v20240208 - 12.0.10 + 9.4.55.v20240627 + 12.0.11 1.65.0 4.1.111.Final 2.0.13 @@ -588,7 +588,7 @@ org.checkerframework checker-qual - 3.44.0 + 3.45.0 provided @@ -718,7 +718,7 @@ com.fasterxml.jackson.core jackson-core - 2.17.1 + 2.17.2 joda-time From 455f4c7b5c4cd84820e8621e48a69085fc52d233 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Mon, 8 Jul 2024 17:37:12 +1000 Subject: [PATCH 26/28] Update Jetty versions to 9.4.55 and 12.0.11 Signed-off-by: Lachlan Roberts --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ccb397d94..bb343b812 100644 --- a/pom.xml +++ b/pom.xml @@ -62,8 +62,8 @@ 1.8 1.8 UTF-8 - 9.4.54.v20240208 - 12.0.10 + 9.4.55.v20240627 + 12.0.11 1.65.0 4.1.111.Final 2.0.13 From 422077b301c265e1e25e96c7e69ca2c44e32cd05 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Tue, 9 Jul 2024 15:02:08 +1000 Subject: [PATCH 27/28] Fix known roles in the DevAppEngineWebAppContext for EE10 Signed-off-by: Lachlan Roberts --- .../development/jetty/ee10/DevAppEngineWebAppContext.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/local_jetty12_ee10/src/main/java/com/google/appengine/tools/development/jetty/ee10/DevAppEngineWebAppContext.java b/runtime/local_jetty12_ee10/src/main/java/com/google/appengine/tools/development/jetty/ee10/DevAppEngineWebAppContext.java index d8c7a2c92..e30812d5c 100644 --- a/runtime/local_jetty12_ee10/src/main/java/com/google/appengine/tools/development/jetty/ee10/DevAppEngineWebAppContext.java +++ b/runtime/local_jetty12_ee10/src/main/java/com/google/appengine/tools/development/jetty/ee10/DevAppEngineWebAppContext.java @@ -23,6 +23,7 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.logging.Logger; import org.eclipse.jetty.ee10.servlet.security.ConstraintMapping; import org.eclipse.jetty.ee10.servlet.security.ConstraintSecurityHandler; @@ -197,9 +198,8 @@ private void disableTransportGuarantee() { mappings.add(mapping); } - // TODO: do we need to call this with a new list or is modifying the ConstraintMapping - // enough? - securityHandler.setConstraintMappings(mappings); + Set knownRoles = Set.copyOf(securityHandler.getKnownRoles()); + securityHandler.setConstraintMappings(mappings, knownRoles); } transportGuaranteesDisabled = true; } From 163a4a3fc99a041747b6cf24f8e8bd4544407f3b Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Tue, 9 Jul 2024 16:00:32 +1000 Subject: [PATCH 28/28] Fixes and cleanups in EE10AppEngineAuthentication Signed-off-by: Lachlan Roberts --- .../jetty/EE10AppEngineAuthentication.java | 91 ++++++------------- 1 file changed, 28 insertions(+), 63 deletions(-) diff --git a/shared_sdk_jetty12/src/main/java/com/google/apphosting/runtime/jetty/EE10AppEngineAuthentication.java b/shared_sdk_jetty12/src/main/java/com/google/apphosting/runtime/jetty/EE10AppEngineAuthentication.java index 7e66d1495..d20ce12d7 100644 --- a/shared_sdk_jetty12/src/main/java/com/google/apphosting/runtime/jetty/EE10AppEngineAuthentication.java +++ b/shared_sdk_jetty12/src/main/java/com/google/apphosting/runtime/jetty/EE10AppEngineAuthentication.java @@ -21,24 +21,21 @@ import com.google.appengine.api.users.UserServiceFactory; import com.google.apphosting.api.ApiProxy; import com.google.common.flogger.GoogleLogger; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; import java.security.Principal; import java.util.Arrays; import java.util.HashSet; import java.util.function.Function; import javax.security.auth.Subject; -import org.eclipse.jetty.ee10.servlet.ServletContextRequest; import org.eclipse.jetty.ee10.servlet.security.ConstraintSecurityHandler; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.security.AuthenticationState; import org.eclipse.jetty.security.Authenticator; import org.eclipse.jetty.security.Constraint; import org.eclipse.jetty.security.DefaultIdentityService; import org.eclipse.jetty.security.IdentityService; import org.eclipse.jetty.security.LoginService; -import org.eclipse.jetty.security.ServerAuthException; +import org.eclipse.jetty.security.SecurityHandler; import org.eclipse.jetty.security.UserIdentity; import org.eclipse.jetty.security.authentication.LoginAuthenticator; import org.eclipse.jetty.server.Request; @@ -157,7 +154,7 @@ public Constraint.Authorization getConstraintAuthentication( * j.c.g.apphosting.utils.jetty.AppEngineAuthentication.AppEngineAuthenticator.authenticate(). * *

If authentication is required but the request comes from an untrusted ip, 307s the request - * back to the trusted appserver. Otherwise it will auth the request and return a login url if + * back to the trusted appserver. Otherwise, it will auth the request and return a login url if * needed. * *

From org.eclipse.jetty.server.Authentication: @@ -165,65 +162,40 @@ public Constraint.Authorization getConstraintAuthentication( * @param req The request * @param res The response * @param cb The callback - * @throws ServerAuthException if an error occurred */ @Override - public AuthenticationState validateRequest(Request req, Response res, Callback cb) - throws ServerAuthException { - - ServletContextRequest contextRequest = Request.as(req, ServletContextRequest.class); - HttpServletRequest request = contextRequest.getServletApiRequest(); - HttpServletResponse response = contextRequest.getHttpServletResponse(); + public AuthenticationState validateRequest(Request req, Response res, Callback cb) { + UserService userService = UserServiceFactory.getUserService(); + // If the user is authenticated already, just create a + // AppEnginePrincipal or AppEngineFederatedPrincipal for them. + if (userService.isUserLoggedIn()) { + UserIdentity user = _loginService.login(null, null, null, null); + logger.atFine().log("authenticate() returning new principal for %s", user); + if (user != null) { + return new UserAuthenticationSucceeded(getAuthenticationType(), user); + } + } - if (response == null) { - throw new ServerAuthException("validateRequest called with null response!!!"); + if (AuthenticationState.Deferred.isDeferred(res)) { + return null; } try { - UserService userService = UserServiceFactory.getUserService(); - // If the user is authenticated already, just create a - // AppEnginePrincipal or AppEngineFederatedPrincipal for them. - if (userService.isUserLoggedIn()) { - UserIdentity user = _loginService.login(null, null, null, null); - logger.atFine().log("authenticate() returning new principal for %s", user); - if (user != null) { - return new UserAuthenticationSucceeded(getAuthenticationType(), user); - } - } - - if (AuthenticationState.Deferred.isDeferred(res)) { - return null; - } - - try { - logger.atFine().log( - "Got %s but no one was logged in, redirecting.", request.getRequestURI()); - String url = userService.createLoginURL(getFullURL(request)); - response.sendRedirect(url); - // Tell Jetty that we've already committed a response here. - return AuthenticationState.CHALLENGE; - } catch (ApiProxy.ApiProxyException ex) { - // If we couldn't get a login URL for some reason, return a 403 instead. - logger.atSevere().withCause(ex).log("Could not get login URL:"); - response.sendError(HttpServletResponse.SC_FORBIDDEN); - return AuthenticationState.SEND_FAILURE; - } - } catch (IOException ex) { - throw new ServerAuthException(ex); + logger.atFine().log( + "Got %s but no one was logged in, redirecting.", req.getHttpURI().getPath()); + String url = userService.createLoginURL(HttpURI.build(req.getHttpURI()).asString()); + Response.sendRedirect(req, res, cb, url); + // Tell Jetty that we've already committed a response here. + return AuthenticationState.CHALLENGE; + } catch (ApiProxy.ApiProxyException ex) { + // If we couldn't get a login URL for some reason, return a 403 instead. + logger.atSevere().withCause(ex).log("Could not get login URL:"); + Response.writeError(req, res, cb, HttpServletResponse.SC_FORBIDDEN); + return AuthenticationState.SEND_FAILURE; } } } - /** Returns the full URL of the specified request, including any query string. */ - private static String getFullURL(HttpServletRequest request) { - StringBuffer buffer = request.getRequestURL(); - if (request.getQueryString() != null) { - buffer.append('?'); - buffer.append(request.getQueryString()); - } - return buffer.toString(); - } - /** * {@code AppEngineLoginService} is a custom Jetty {@link LoginService} that is aware of the two * special role names implemented by Google App Engine. Any authenticated user is a member of the @@ -279,13 +251,6 @@ public void setIdentityService(IdentityService identityService) { this.identityService = identityService; } - /** - * Validate a user identity. Validate that a UserIdentity previously created by a call to {@link - * #login(String, Object, ServletRequest)} is still valid. - * - * @param user The user to validate - * @return true if authentication has not been revoked for the user. - */ @Override public boolean validate(UserIdentity user) { logger.atInfo().log("validate(%s) throwing UnsupportedOperationException.", user); @@ -310,7 +275,7 @@ public User getUser() { @Override public String getName() { - if ((user.getFederatedIdentity() != null) && (user.getFederatedIdentity().length() > 0)) { + if ((user.getFederatedIdentity() != null) && (!user.getFederatedIdentity().isEmpty())) { return user.getFederatedIdentity(); } return user.getEmail();