Add a configuration to serve a local directory with a static handler
Summary
This PR introduces support for serving static files from a local directory,
configurable via quarkus.http.local-static-resources.*.
New configuration
quarkus.http.local-static-resources.enabled=true quarkus.http.local-static-resources.path=/local-static/ quarkus.http.local-static-resources.directory=local-static
Tests
Added LocalStaticResourcesTest which verifies:
- Serving an existing file
- Returning 404 when missing
I also forgot, you need to add those files as watched for livereload
I also forgot, you need to add those files as watched for livereload
ii have added @ia3andy
Improve validation and handling of local static resources directory
- Introduce normalizedDirectory() with safety checks
- I used validated directory in both build steps
- Remove unnecessary endpoint trailing-slash logic
- Simplify dev-mode directory guard
@mathias82 the code is LGTM, could you add the doc part also, I remember an old doc doing this with the StaticHandler (which was bad), but maybe it was removed.
:waning_crescent_moon: This workflow status is outdated as a new workflow run has been triggered.
Status for workflow Quarkus CI
This is the status report for running Quarkus CI on commit c41696b47f04b137a242b7152ecef36b365a6887.
Failing Jobs
| Status | Name | Step | Failures | Logs | Raw logs | Build scan |
|---|---|---|---|---|---|---|
| :x: | Initial JDK 17 Build | Build |
Failures | Logs | Raw logs | :mag: |
You can consult the Develocity build scans.
Failures
:gear: Initial JDK 17 Build #
- Failing: extensions/vertx-http/runtime
! Skipped: devtools/bom-descriptor-json devtools/cli docs and 615 more
:package: extensions/vertx-http/runtime
:x: Failed to execute goal net.revelc.code.formatter:formatter-maven-plugin:2.27.0:validate (default) on project quarkus-vertx-http: File '/home/runner/_work/quarkus/quarkus/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/LocalStaticResourcesConfig.java' has not been previously formatted. Please format file (for example by invoking `mvn -f extensions/vertx-http/runtime net.revelc.code.formatter:formatter-maven-plugin:2.27.0:format`) and commit before running validation!
@ia3andy Thanks! I’ve updated the documentation. If there’s any other area in Quarkus where you think an improvement is needed related to HTTP, Vert.x, static resources, or anything else I’m happy to take it on. Just let me know!
:waning_crescent_moon: This workflow status is outdated as a new workflow run has been triggered.
Status for workflow Quarkus CI
This is the status report for running Quarkus CI on commit 76d924b00e80e12c2fc557890f807c8422f6ae46.
Failing Jobs
| Status | Name | Step | Failures | Logs | Raw logs | Build scan |
|---|---|---|---|---|---|---|
| :x: | Initial JDK 17 Build | Build |
Failures | Logs | Raw logs | :mag: |
You can consult the Develocity build scans.
Failures
:gear: Initial JDK 17 Build #
- Failing: extensions/vertx-http/runtime
! Skipped: devtools/bom-descriptor-json devtools/cli docs and 615 more
:package: extensions/vertx-http/runtime
:x: Failed to execute goal net.revelc.code.formatter:formatter-maven-plugin:2.27.0:validate (default) on project quarkus-vertx-http: File '/home/runner/_work/quarkus/quarkus/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/LocalStaticResourcesConfig.java' has not been previously formatted. Please format file (for example by invoking `mvn -f extensions/vertx-http/runtime net.revelc.code.formatter:formatter-maven-plugin:2.27.0:format`) and commit before running validation!
:waning_crescent_moon: This workflow status is outdated as a new workflow run has been triggered.
Status for workflow Quarkus Documentation CI
This is the status report for running Quarkus Documentation CI on commit 76d924b00e80e12c2fc557890f807c8422f6ae46.
:white_check_mark: The latest workflow run for the pull request has completed successfully.
It should be safe to merge provided you have a look at the other checks in the summary.
🎊 PR Preview b792b260dff415f4f0c5a54873b7efd94bc656f2 has been successfully built and deployed to https://quarkus-pr-main-51186-preview.surge.sh/version/main/guides/
- Images of blog posts older than 3 months are not available.
- Newsletters older than 3 months are not available.
:waning_crescent_moon: This workflow status is outdated as a new workflow run has been triggered.
Status for workflow Quarkus CI
This is the status report for running Quarkus CI on commit 04835e2e94d17875a13cd9946b7f5e375ac6f356.
Failing Jobs
| Status | Name | Step | Failures | Logs | Raw logs | Build scan |
|---|---|---|---|---|---|---|
| :x: | Initial JDK 17 Build | Build |
Failures | Logs | Raw logs | :mag: |
You can consult the Develocity build scans.
Failures
:gear: Initial JDK 17 Build #
- Failing: extensions/vertx-http/runtime
! Skipped: devtools/bom-descriptor-json devtools/cli docs and 615 more
:package: extensions/vertx-http/runtime
:x: Failed to execute goal net.revelc.code:impsort-maven-plugin:1.12.0:check (check-imports) on project quarkus-vertx-http: Imports are not sorted in /home/runner/_work/quarkus/quarkus/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/LocalStaticResourcesConfig.java
:waning_crescent_moon: This workflow status is outdated as a new workflow run has been triggered.
Status for workflow Quarkus Documentation CI
This is the status report for running Quarkus Documentation CI on commit 04835e2e94d17875a13cd9946b7f5e375ac6f356.
:white_check_mark: The latest workflow run for the pull request has completed successfully.
It should be safe to merge provided you have a look at the other checks in the summary.
:waning_crescent_moon: This workflow status is outdated as a new workflow run has been triggered.
Status for workflow Quarkus Documentation CI
This is the status report for running Quarkus Documentation CI on commit 305db021586712eccdd2c5d02c869e2e1b3a8bc6.
:white_check_mark: The latest workflow run for the pull request has completed successfully.
It should be safe to merge provided you have a look at the other checks in the summary.
[!WARNING] There are other workflow runs running, you probably need to wait for their status before merging.
:waning_crescent_moon: This workflow status is outdated as a new workflow run has been triggered.
Status for workflow Quarkus Documentation CI
This is the status report for running Quarkus Documentation CI on commit 5eda9a9a182085e1c1620420b36d264a309b0e03.
:white_check_mark: The latest workflow run for the pull request has completed successfully.
It should be safe to merge provided you have a look at the other checks in the summary.
[!WARNING] There are other workflow runs running, you probably need to wait for their status before merging.
@ia3andy do you know why its failing the jvm tests?
:waning_crescent_moon: This workflow status is outdated as a new workflow run has been triggered.
Status for workflow Quarkus CI
This is the status report for running Quarkus CI on commit 5eda9a9a182085e1c1620420b36d264a309b0e03.
Failing Jobs
| Status | Name | Step | Failures | Logs | Raw logs | Build scan |
|---|---|---|---|---|---|---|
| :x: | JVM Tests - JDK 17 | Build |
Failures | Logs | Raw logs | :mag: |
| :x: | JVM Tests - JDK 21 | Build |
Failures | Logs | Raw logs | :mag: |
| :x: | JVM Tests - JDK 21 Semeru | Build |
Failures | Logs | Raw logs | :mag: |
| :x: | JVM Tests - JDK 25 | Build |
Failures | Logs | Raw logs | :mag: |
| :x: | JVM Tests - JDK 17 Windows | Build |
Failures | Logs | Raw logs | :mag: |
Full information is available in the Build summary check run. You can consult the Develocity build scans.
Failures
:gear: JVM Tests - JDK 17 #
- Failing: extensions/vertx-http/deployment
! Skipped: devtools/cli extensions/agroal/deployment extensions/amazon-lambda-http/deployment and 141 more
:package: extensions/vertx-http/deployment
:x: io.quarkus.vertx.http.LocalStaticResourcesTest. - History - More details - Source on GitHub
java.lang.RuntimeException: Unable to create the archive
at io.quarkus.test.QuarkusUnitTest.exportArchives(QuarkusUnitTest.java:375)
at io.quarkus.test.QuarkusUnitTest.beforeAll(QuarkusUnitTest.java:614)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: java.lang.IllegalArgumentException: application-local-static-resources.properties doesn't exist or can't be accessed
at org.jboss.shrinkwrap.impl.base.Validate.notNull(Validate.java:43)
at org.jboss.shrinkwrap.impl.base.container.ContainerBase.fileFromResource(ContainerBase.java:1991)
at org.jboss.shrinkwrap.impl.base.container.ContainerBase.addAsResource(ContainerBase.java:1057)
:gear: JVM Tests - JDK 21 #
- Failing: extensions/vertx-http/deployment
! Skipped: devtools/cli extensions/agroal/deployment extensions/amazon-lambda-http/deployment and 141 more
:package: extensions/vertx-http/deployment
:x: io.quarkus.vertx.http.LocalStaticResourcesTest. - History - More details - Source on GitHub
java.lang.RuntimeException: Unable to create the archive
at io.quarkus.test.QuarkusUnitTest.exportArchives(QuarkusUnitTest.java:375)
at io.quarkus.test.QuarkusUnitTest.beforeAll(QuarkusUnitTest.java:614)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: java.lang.IllegalArgumentException: application-local-static-resources.properties doesn't exist or can't be accessed
at org.jboss.shrinkwrap.impl.base.Validate.notNull(Validate.java:43)
at org.jboss.shrinkwrap.impl.base.container.ContainerBase.fileFromResource(ContainerBase.java:1991)
at org.jboss.shrinkwrap.impl.base.container.ContainerBase.addAsResource(ContainerBase.java:1057)
:gear: JVM Tests - JDK 21 Semeru #
- Failing: extensions/vertx-http/deployment
! Skipped: devtools/cli extensions/agroal/deployment extensions/amazon-lambda-http/deployment and 141 more
:package: extensions/vertx-http/deployment
:x: io.quarkus.vertx.http.LocalStaticResourcesTest. - History - More details - Source on GitHub
java.lang.RuntimeException: Unable to create the archive
at io.quarkus.test.QuarkusUnitTest.exportArchives(QuarkusUnitTest.java:375)
at io.quarkus.test.QuarkusUnitTest.beforeAll(QuarkusUnitTest.java:614)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: java.lang.IllegalArgumentException: application-local-static-resources.properties doesn't exist or can't be accessed
at org.jboss.shrinkwrap.impl.base.Validate.notNull(Validate.java:43)
at org.jboss.shrinkwrap.impl.base.container.ContainerBase.fileFromResource(ContainerBase.java:1991)
at org.jboss.shrinkwrap.impl.base.container.ContainerBase.addAsResource(ContainerBase.java:1057)
:gear: JVM Tests - JDK 25 #
- Failing: extensions/vertx-http/deployment
! Skipped: devtools/cli extensions/agroal/deployment extensions/amazon-lambda-http/deployment and 141 more
:package: extensions/vertx-http/deployment
:x: io.quarkus.vertx.http.LocalStaticResourcesTest. - History - More details - Source on GitHub
java.lang.RuntimeException: Unable to create the archive
at io.quarkus.test.QuarkusUnitTest.exportArchives(QuarkusUnitTest.java:375)
at io.quarkus.test.QuarkusUnitTest.beforeAll(QuarkusUnitTest.java:614)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
Caused by: java.lang.IllegalArgumentException: application-local-static-resources.properties doesn't exist or can't be accessed
at org.jboss.shrinkwrap.impl.base.Validate.notNull(Validate.java:43)
at org.jboss.shrinkwrap.impl.base.container.ContainerBase.fileFromResource(ContainerBase.java:1991)
at org.jboss.shrinkwrap.impl.base.container.ContainerBase.addAsResource(ContainerBase.java:1057)
:gear: JVM Tests - JDK 17 Windows #
- Failing: extensions/vertx-http/deployment
! Skipped: devtools/cli extensions/agroal/deployment extensions/amazon-lambda-http/deployment and 141 more
:package: extensions/vertx-http/deployment
:x: io.quarkus.vertx.http.LocalStaticResourcesTest. - History - More details - Source on GitHub
java.lang.RuntimeException: Unable to create the archive
at io.quarkus.test.QuarkusUnitTest.exportArchives(QuarkusUnitTest.java:375)
at io.quarkus.test.QuarkusUnitTest.beforeAll(QuarkusUnitTest.java:614)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: java.lang.IllegalArgumentException: application-local-static-resources.properties doesn't exist or can't be accessed
at org.jboss.shrinkwrap.impl.base.Validate.notNull(Validate.java:43)
at org.jboss.shrinkwrap.impl.base.container.ContainerBase.fileFromResource(ContainerBase.java:1991)
at org.jboss.shrinkwrap.impl.base.container.ContainerBase.addAsResource(ContainerBase.java:1057)
Flaky tests - Develocity
:gear: MicroProfile TCKs Tests
:package: tcks/microprofile-lra
:x: org.eclipse.microprofile.lra.tck.TckRecoveryTests.testCancelWhenParticipantIsUnavailable - History
Expecting the metric Compensated callback was called Expected: a value equal to or greater than <1> but: <0> was less than <1>-java.lang.AssertionError
java.lang.AssertionError:
Expecting the metric Compensated callback was called
Expected: a value equal to or greater than <1>
but: <0> was less than <1>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.eclipse.microprofile.lra.tck.TckRecoveryTests.assertMetricCallbackCalled(TckRecoveryTests.java:210)
at org.eclipse.microprofile.lra.tck.TckRecoveryTests.testCancelWhenParticipantIsUnavailable(TckRecoveryTests.java:195)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Probably your test not passing
Not strictly against it as it does sound useful indeed, however it makes me a bit nervous from a security standpoint. Could we be extra cautious when introducing such a feature?
I'm not a security expert myself but let's at least impose some principles of directory traversal sanitation and scope restrictions; ideally if it has such a feature, we'd expect the server to run with restricted privileges and restricted access via selinux so perhaps some bootstrap hints or documentation suggestions would be in order.
It would be critical to verify one can't escape the designated directory via various path patterns, such as ../../ and its analogous http-encoded forms; regarding scoping restrictions: perhaps restrict the scope to read-only files with a certain set of extensions which need to be whitelisted explicitly at build time? Impose a certain root like wwwroot or public_html to make sure it's not being tricked into serving system configuration?
Having glanced at the PR, it looks like delegating to Vert.x so maybe it's all good already - I'm just asking to check carefully. Can we assume Vert.x is applying restrictions safely? Would be nice to add some tests at least verifying a directory traversal attempt would get blocked.
@darranl any more guidance, restrictions or a flat-out veto?
We can of course relax some requirements in dev-mode; e.g. I wouldn't expect the process to run with restricted permissions in such case, but it would need to work consistently to prod mode in regards to any other filters being applied.
Hi @Sanne , I went through all the concerns you raised and implemented the required safety checks:
• Normalized and validated both path and directory (reject .., *, absolute paths, spaces, backslashes).
• Both build steps use normalizedDirectory() and resolve it to an absolute, normalized root.
• Relativized file paths are normalized and any path containing .. is skipped defensively.
• Only files strictly under the configured directory are served (via Files.walk(root)).
I also added tests verifying:
• serving a valid file,
• 404 for missing files,
• 404 for traversal attempts (../, nested ../../, and URL-encoded ..).
@ia3andy All tests in extensions/vertx-http pass locally, including the new negative
cases for traversal attempts:
./mvnw -pl extensions/vertx-http/deployment test
I also executed the Spring Web integration test locally to verify the CI failure: ./mvnw -pl integration-tests/spring-web -Dtest=SpringSchedulerTest test
java.util.ServiceConfigurationError: io.quarkus.runtime.test.TestHttpEndpointProvider: io.quarkus.spring.web.runtime.SpringWebEndpointProvider not a subtype
This occurs even without my changes applied, so it appears unrelated to this PR and likely caused by a mismatch in the Spring Web test SPI on main.
Once that issue is resolved or a rebase lands, this PR should go green.
thanks
:waning_crescent_moon: This workflow status is outdated as a new workflow run has been triggered.
Status for workflow Quarkus Documentation CI
This is the status report for running Quarkus Documentation CI on commit 901ea63cd7fa1d661bdd4a276c7c75d003eee575.
:white_check_mark: The latest workflow run for the pull request has completed successfully.
It should be safe to merge provided you have a look at the other checks in the summary.
[!WARNING] There are other workflow runs running, you probably need to wait for their status before merging.
:waning_crescent_moon: This workflow status is outdated as a new workflow run has been triggered.
Status for workflow Quarkus CI
This is the status report for running Quarkus CI on commit 901ea63cd7fa1d661bdd4a276c7c75d003eee575.
Failing Jobs
| Status | Name | Step | Failures | Logs | Raw logs | Build scan |
|---|---|---|---|---|---|---|
| :heavy_check_mark: | JVM Tests - JDK 17 | Logs | Raw logs | :construction: | ||
| :x: | JVM Tests - JDK 21 | Build |
Failures | Logs | Raw logs | :construction: |
| :heavy_check_mark: | JVM Tests - JDK 21 Semeru | Logs | Raw logs | :construction: | ||
| :heavy_check_mark: | JVM Tests - JDK 25 | Logs | Raw logs | :construction: | ||
| :x: | JVM Tests - JDK 17 Windows | Build |
:warning: Check → | Logs | Raw logs | :construction: |
| :heavy_check_mark: | JVM Integration Tests - JDK 17 | Logs | Raw logs | :construction: | ||
| :heavy_check_mark: | JVM Integration Tests - JDK 17 Windows | Logs | Raw logs | :construction: | ||
| :x: | JVM Integration Tests - JDK 21 | Build |
Failures | Logs | Raw logs | :construction: |
| :heavy_check_mark: | JVM Integration Tests - JDK 21 Semeru | Logs | Raw logs | :construction: | ||
| :heavy_check_mark: | JVM Integration Tests - JDK 25 | Logs | Raw logs | :construction: |
Full information is available in the Build summary check run. You can consult the Develocity build scans.
Failures
:gear: JVM Tests - JDK 21 #
- Failing: extensions/panache/hibernate-orm-rest-data-panache/deployment
:package: extensions/panache/hibernate-orm-rest-data-panache/deployment
:x: io.quarkus.hibernate.orm.rest.data.panache.deployment.build.BuildConditionsWithResourceDisabledTest. - History - More details - Source on GitHub
java.lang.RuntimeException: Failed to start quarkus
at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
at io.quarkus.runtime.Application.start(Application.java:101)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at io.quarkus.runner.bootstrap.StartupActionImpl.run(StartupActionImpl.java:350)
at io.quarkus.test.QuarkusUnitTest.beforeAll(QuarkusUnitTest.java:703)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: java.lang.RuntimeException: java.lang.OutOfMemoryError: Metaspace
:gear: JVM Integration Tests - JDK 21 #
- Failing: integration-tests/spring-web
:package: integration-tests/spring-web
:x: io.quarkus.it.spring.web.SpringSchedulerTest. - History - More details - Source on GitHub
org.junit.jupiter.engine.execution.ConditionEvaluationException: Failed to evaluate condition [io.quarkus.test.junit.QuarkusTestExtension]: Internal error: Test class was loaded with an unexpected classloader (QuarkusClassLoader:Quarkus Base Runtime ClassLoader: TEST for JUnitQuarkusTest-no-profile (QuarkusTest)@1f1574c) or the thread context classloader (jdk.internal.loader.ClassLoaders$AppClassLoader@c387f44) was incorrect.
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1685)
at java.base/java.util.stream.Reference...
:x: io.quarkus.it.spring.web.SpringSchedulerTest.testCount line 22 - History - More details - Source on GitHub
org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
at org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:36)
at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:31)
at org.junit.jupiter.api.Assertions.assertTrue(Assertions.java:183)
at io.quarkus.it.spring.web.SpringSchedulerTest.testCount(SpringSchedulerTest.java:22)
Flaky tests - Develocity
:gear: JVM Tests - JDK 21 Semeru
:package: extensions/micrometer-opentelemetry/deployment
:x: io.quarkus.micrometer.opentelemetry.deployment.compatibility.MicrometerTimedInterceptorTest.testTimeMethod_Failed - History
Stream has no elements-java.lang.IllegalArgumentException
java.lang.IllegalArgumentException: Stream has no elements
at io.quarkus.micrometer.opentelemetry.deployment.common.MetricDataFilter.lastReadingDataPoint(MetricDataFilter.java:236)
at io.quarkus.micrometer.opentelemetry.deployment.compatibility.MicrometerTimedInterceptorTest.testTimeMethod_Failed(MicrometerTimedInterceptorTest.java:100)
at java.base/java.lang.reflect.Method.invoke(Method.java:586)
at io.quarkus.test.QuarkusUnitTest.runExtensionMethod(QuarkusUnitTest.java:532)
at io.quarkus.test.QuarkusUnitTest.interceptTestMethod(QuarkusUnitTest.java:446)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
:gear: MicroProfile TCKs Tests
:package: tcks/microprofile-lra
:x: org.eclipse.microprofile.lra.tck.TckRecoveryTests.testCancelWhenParticipantIsUnavailable - History
Expecting the metric Compensated callback was called Expected: a value equal to or greater than <1> but: <0> was less than <1>-java.lang.AssertionError
java.lang.AssertionError:
Expecting the metric Compensated callback was called
Expected: a value equal to or greater than <1>
but: <0> was less than <1>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.eclipse.microprofile.lra.tck.TckRecoveryTests.assertMetricCallbackCalled(TckRecoveryTests.java:210)
at org.eclipse.microprofile.lra.tck.TckRecoveryTests.testCancelWhenParticipantIsUnavailable(TckRecoveryTests.java:195)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
:waning_crescent_moon: This workflow status is outdated as a new workflow run has been triggered.
Status for workflow Quarkus Documentation CI
This is the status report for running Quarkus Documentation CI on commit d73885baf85269f192bdbb986f5a932a2ff809ef.
:white_check_mark: The latest workflow run for the pull request has completed successfully.
It should be safe to merge provided you have a look at the other checks in the summary.
[!WARNING] There are other workflow runs running, you probably need to wait for their status before merging.
@Sanne have a look at the issue, it's already the second implementation for this. We considered security by:
- Once built, everything is in the jar like any other resources and served with vertx static handler
- During build we check for
..to avoid going up the path as an extra security
Anyway, any extra caution is very welcome and I agree that it is a sensitive feature.
@mathias82 Windows test fails:
28m 11s
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.21 s -- in io.quarkus.vertx.http.testrunner.ChangeSourceAndTestAtOnceTestCase
[INFO] Running io.quarkus.vertx.http.testrunner.QuarkusTestTypeTestCase
Tests paused
Running tests for the first time
2025-11-26 06:57:35,823 INFO [org.eclipse.aether.internal.impl.filter.GroupIdRemoteRepositoryFilterSource] (main) Loaded 1 groupId for remote repository gradle
2025-11-26 06:57:38,482 WARN [io.quarkus.bootstrap.BootstrapAppModelFactory] (build-5) Expected project directory D:\a\quarkus\quarkus\extensions\vertx-http\deployment\target\quarkus-dev-mode-test2135290939935675679 does not match current project directory D:\a\quarkus\quarkus\extensions\vertx-http\deployment
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2025-11-26 06:57:42,764 WARN [io.quarkus.config] (Quarkus Main Thread) Unrecognized configuration key "quarkus.continuous-tests-discovery" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo
2025-11-26 06:57:44,021 INFO [io.quarkus] (Quarkus Main Thread) quarkus-vertx-http-deployment 999-SNAPSHOT on JVM (powered by Quarkus 999-SNAPSHOT) started in 7.098s. Listening on: http://localhost:8080
2025-11-26 06:57:44,021 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2025-11-26 06:57:44,021 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, security, smallrye-context-propagation, vertx]
Starting test run, 2 tests to run.
Running 1/2. Running: #JUnit Jupiter
Running 1/2. Running: io.quarkus.vertx.http.testrunner.SimpleET#SimpleET
2025-11-26 06:57:46,691 INFO [io.quarkus] (Test runner thread) quarkus-vertx-http-deployment 999-SNAPSHOT on JVM (powered by Quarkus 999-SNAPSHOT) started in 5.136s. Listening on: http://localhost:8081
2025-11-26 06:57:46,691 INFO [io.quarkus] (Test runner thread) Profile test activated.
2025-11-26 06:57:46,691 INFO [io.quarkus] (Test runner thread) Installed features: [cdi, security, smallrye-context-propagation, vertx]
Running 1/2. Running: io.quarkus.vertx.http.testrunner.SimpleET#testHelloEndpoint()
Request method: GET
Request URI: http://localhost:8081/hello
Proxy: <none>
Request params: <none>
Query params: <none>
Form params: <none>
Path params: <none>
Headers: Accept=*/*
Cookies: <none>
Multiparts: <none>
Body: <none>
HTTP/1.1 404 Not Found
content-type: text/html; charset=utf-8
content-length: 53
<html>
<body>
<h1>Resource not found</h1>
</body>
</html>
Running 2/2. 1 failure so far. Running: io.quarkus.vertx.http.testrunner.SimpleET#testGreetingEndpoint()
2025-11-26 06:57:47,854 INFO [io.quarkus] (Test runner thread) quarkus-vertx-http-deployment(test application) stopped in 0.023s
2025-11-26 06:57:47,860 ERROR [io.quarkus.test] (Test runner thread) ==================== TEST REPORT #1 ====================
2025-11-26 06:57:47,860 ERROR [io.quarkus.test] (Test runner thread) Test SimpleET#testHelloEndpoint() failed
: java.lang.AssertionError: 1 expectation failed.
Expected status code <200> but was <404>.
at io.restassured.internal.ValidatableResponseOptionsImpl.statusCode(ValidatableResponseOptionsImpl.java:89)
at io.quarkus.vertx.http.testrunner.SimpleET.testHelloEndpoint(SimpleET.java:20)
2025-11-26 06:57:47,861 ERROR [io.quarkus.test] (Test runner thread) >>>>>>>>>>>>>>>>>>>> Summary: <<<<<<<<<<<<<<<<<<<<
io.quarkus.vertx.http.testrunner.SimpleET#testHelloEndpoint(SimpleET.java:20) SimpleET#testHelloEndpoint() 1 expectation failed.
Expected status code <200> but was <404>.
2025-11-26 06:57:47,862 ERROR [io.quarkus.test] (Test runner thread) >>>>>>>>>>>>>>>>>>>> 1 TEST FAILED <<<<<<<<<<<<<<<<<<<<
@ia3andy Thanks for pointing this out! Locally (on Linux) all tests pass for me, including the vertx-http module.
The failure on Windows seems to come from SimpleET#testHelloEndpoint() returning 404 for /hello.
In this PR I only added LocalStaticResourcesTest which uses QuarkusUnitTest and overrides quarkus.http.local-static-resources.* inside that test class only, so it shouldn’t affect the dev-mode test runner or the /hello endpoint.
Is this a known flakiness on Windows for the SimpleET tests, or is there anything specific you’d like me to change in the PR?
IMHO, as long as this configuration is build time, which it is, and therefore can not be changed dynamically, it is safe as it can't be overridden, as long as the application is not built or run in the hostile environment, in which case a lot of other negative side-effects can happen, besides modifying this particular configuration
@mathias82 many thanks for the quick improvements!
@sberyozkin :
IMHO, as long as this configuration is build time, which it is, and therefore can not be changed dynamically, it is safe as it can't be overridden, as long as the application is not built or run in the hostile environment, in which case a lot of other negative side-effects can happen, besides modifying this particular configuration
Sure if the app is run in a "hostile environment" all bets are off. I'm not asking to consider this scenario.
But even though the root path might be checked at build time, it's the paths that are generated relatively to the root path that concern me.
:waning_crescent_moon: This workflow status is outdated as a new workflow run has been triggered.
Status for workflow Quarkus CI
This is the status report for running Quarkus CI on commit d73885baf85269f192bdbb986f5a932a2ff809ef.
Failing Jobs
| Status | Name | Step | Failures | Logs | Raw logs | Build scan |
|---|---|---|---|---|---|---|
| :heavy_check_mark: | JVM Tests - JDK 17 | Logs | Raw logs | :construction: | ||
| :heavy_check_mark: | JVM Tests - JDK 21 | Logs | Raw logs | :construction: | ||
| :heavy_check_mark: | JVM Tests - JDK 21 Semeru | Logs | Raw logs | :construction: | ||
| :x: | JVM Tests - JDK 25 | Build |
Failures | Logs | Raw logs | :construction: |
| :x: | JVM Tests - JDK 17 Windows | Build |
Failures | Logs | Raw logs | :mag: |
Full information is available in the Build summary check run. You can consult the Develocity build scans.
Failures
:gear: JVM Tests - JDK 25 #
- Failing: extensions/opentelemetry/deployment
! Skipped: extensions/liquibase/liquibase-mongodb/deployment extensions/micrometer-opentelemetry/deployment extensions/micrometer-registry-prometheus/deployment and 10 more
:package: extensions/opentelemetry/deployment
:x: io.quarkus.opentelemetry.deployment.logs.LoggingFrameworkTest. - History - More details - Source on GitHub
java.lang.RuntimeException:
io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkus.arc.deployment.ArcProcessor#validate threw an exception: java.lang.NullPointerException: Cannot invoke "io.quarkus.arc.processor.InjectionPointInfo.isProgrammaticLookup()" because "injectionPoint" is null
at io.quarkus.arc.processor.UnusedBeans.findRemovableBeans(UnusedBeans.java:44)
at io.quarkus.arc.processor.BeanDeployment.removeUnusedBeans(BeanDeployment.java:498)
at io.quarkus.arc.processor.BeanDeployment.removeUnusedComponents(BeanDeployment.java:407)
at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:354)
at io.quarkus.arc.processor.BeanProcessor.initialize(BeanProcessor.java:177)
:gear: JVM Tests - JDK 17 Windows #
- Failing: extensions/vertx-http/deployment
! Skipped: devtools/cli extensions/agroal/deployment extensions/amazon-lambda-http/deployment and 141 more
:package: extensions/vertx-http/deployment
:x: io.quarkus.vertx.http.proxy.TrustedForwarderDnsResolveTest.testTrustedProxyResolved - History - More details - Source on GitHub
java.io.IOException:
Error while binding on /127.0.0.1:53530
original message : Address already in use: bind
at org.apache.mina.transport.socket.nio.NioDatagramAcceptor.open(NioDatagramAcceptor.java:708)
at org.apache.mina.transport.socket.nio.NioDatagramAcceptor.registerHandles(NioDatagramAcceptor.java:228)
at org.apache.mina.transport.socket.nio.NioDatagramAcceptor.access$300(NioDatagramAcceptor.java:68)
at org.apache.mina.transport.socket.nio.NioDatagramAcceptor$Acceptor.run(NioDatagramAcceptor.java:164)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
Flaky tests - Develocity
:gear: JVM Tests - JDK 21
:package: extensions/micrometer-opentelemetry/deployment
:x: io.quarkus.micrometer.opentelemetry.deployment.compatibility.MicrometerTimedInterceptorTest.testTimeMethod_Uni - History
Stream has no elements-java.lang.IllegalArgumentException
java.lang.IllegalArgumentException: Stream has no elements
at io.quarkus.micrometer.opentelemetry.deployment.common.MetricDataFilter.lambda$lastReading$2(MetricDataFilter.java:213)
at java.base/java.util.Optional.orElseThrow(Optional.java:403)
at io.quarkus.micrometer.opentelemetry.deployment.common.MetricDataFilter.lastReading(MetricDataFilter.java:213)
at io.quarkus.micrometer.opentelemetry.deployment.common.MetricDataFilter.lastReadingDataPoint(MetricDataFilter.java:231)
at io.quarkus.micrometer.opentelemetry.deployment.compatibility.MicrometerTimedInterceptorTest.testTimeMethod_Uni(MicrometerTimedInterceptorTest.java:174)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at io.quarkus.test.QuarkusUnitTest.runExtensionMethod(QuarkusUnitTest.java:532)
:gear: JVM Tests - JDK 21 Semeru
:package: extensions/micrometer-opentelemetry/deployment
:x: io.quarkus.micrometer.opentelemetry.deployment.compatibility.MicrometerTimedInterceptorTest.testTimeMethod_Uni - History
Stream has no elements-java.lang.IllegalArgumentException
java.lang.IllegalArgumentException: Stream has no elements
at io.quarkus.micrometer.opentelemetry.deployment.common.MetricDataFilter.lambda$lastReading$2(MetricDataFilter.java:213)
at java.base/java.util.Optional.orElseThrow(Optional.java:403)
at io.quarkus.micrometer.opentelemetry.deployment.common.MetricDataFilter.lastReading(MetricDataFilter.java:213)
at io.quarkus.micrometer.opentelemetry.deployment.common.MetricDataFilter.lastReadingDataPoint(MetricDataFilter.java:231)
at io.quarkus.micrometer.opentelemetry.deployment.compatibility.MicrometerTimedInterceptorTest.testTimeMethod_Uni(MicrometerTimedInterceptorTest.java:174)
at java.base/java.lang.reflect.Method.invoke(Method.java:586)
at io.quarkus.test.QuarkusUnitTest.runExtensionMethod(QuarkusUnitTest.java:532)
:gear: MicroProfile TCKs Tests
:package: tcks/microprofile-lra
:x: org.eclipse.microprofile.lra.tck.TckRecoveryTests.testCancelWhenParticipantIsUnavailable - History
Expecting the metric Compensated callback was called Expected: a value equal to or greater than <1> but: <0> was less than <1>-java.lang.AssertionError
java.lang.AssertionError:
Expecting the metric Compensated callback was called
Expected: a value equal to or greater than <1>
but: <0> was less than <1>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.eclipse.microprofile.lra.tck.TckRecoveryTests.assertMetricCallbackCalled(TckRecoveryTests.java:210)
at org.eclipse.microprofile.lra.tck.TckRecoveryTests.testCancelWhenParticipantIsUnavailable(TckRecoveryTests.java:195)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
@mathias82 many thanks for the quick improvements!
@sberyozkin :
IMHO, as long as this configuration is build time, which it is, and therefore can not be changed dynamically, it is safe as it can't be overridden, as long as the application is not built or run in the hostile environment, in which case a lot of other negative side-effects can happen, besides modifying this particular configuration
Sure if the app is run in a "hostile environment" all bets are off. I'm not asking to consider this scenario.
But even though the root path might be checked at build time, it's the paths that are generated relatively to the root path that concern me.
How is this implementation different from META-INF/resources?
How is this implementation different from
META-INF/resources?
That's exactly my thought. This is the same feature, with the same implementation in theory.
As far as path resolving goes, normally you take a user-provided URI, then resolve it against the static path you're serving, and if it doesn't start with the static path, you reject it. No need to check for .. or anything fancy.
(note that I didn't check the PR yet)
:waning_crescent_moon: This workflow status is outdated as a new workflow run has been triggered.
Status for workflow Quarkus Documentation CI
This is the status report for running Quarkus Documentation CI on commit bf33ece73c8c153959f23a7dfee543614083fac0.
:white_check_mark: The latest workflow run for the pull request has completed successfully.
It should be safe to merge provided you have a look at the other checks in the summary.
[!WARNING] There are other workflow runs running, you probably need to wait for their status before merging.