diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpBuildTimeConfig.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpBuildTimeConfig.java index a0a8383110a2a1..b8184ff5ed53f7 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpBuildTimeConfig.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpBuildTimeConfig.java @@ -2,9 +2,12 @@ import java.time.Duration; +import org.eclipse.microprofile.config.spi.Converter; + import io.quarkus.runtime.annotations.ConfigItem; import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; +import io.quarkus.runtime.annotations.ConvertWith; import io.vertx.core.http.ClientAuth; @ConfigRoot(name = "http", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) @@ -14,6 +17,7 @@ public class HttpBuildTimeConfig { * The HTTP root path. All web content will be served relative to this root path. */ @ConfigItem(defaultValue = "/") + @ConvertWith(NormalizeHttpRootPathConverter.class) public String rootPath; public AuthConfig auth; @@ -43,7 +47,7 @@ public class HttpBuildTimeConfig { * Non-application endpoints will be served from the specified path. * * `${quarkus.http.root-path}` -> Setting this path to the same value as HTTP root path disables * this root path. All extension-provided endpoints will be served from `${quarkus.http.root-path}`. - * + * * @asciidoclet */ @ConfigItem(defaultValue = "q") @@ -54,4 +58,32 @@ public class HttpBuildTimeConfig { */ @ConfigItem(defaultValue = "30s") public Duration testTimeout; + + /** + * Make sure the HTTP root path is fully normalized and always starts and ends with a '/'. + */ + public static class NormalizeHttpRootPathConverter implements Converter { + + private static final String SLASH = "/"; + + @Override + public String convert(String value) throws IllegalArgumentException, NullPointerException { + if (value == null) { + return SLASH; + } + + value = value.trim(); + if (SLASH.equals(value)) { + return value; + } + if (!value.startsWith(SLASH)) { + value = SLASH + value; + } + if (!value.endsWith(SLASH)) { + value = value + SLASH; + } + + return value; + } + } } diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/StaticResourcesRecorder.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/StaticResourcesRecorder.java index 9dbca79a5143c5..b27894d1bb0190 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/StaticResourcesRecorder.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/StaticResourcesRecorder.java @@ -56,7 +56,7 @@ public Consumer start() { StaticHandler staticHandler = StaticHandler.create(META_INF_RESOURCES).setDefaultContentEncoding("UTF-8"); handlers.add(ctx -> { String rel = ctx.mountPoint() == null ? ctx.normalisedPath() - : ctx.normalisedPath().substring(ctx.mountPoint().length()); + : ctx.normalisedPath().substring(ctx.mountPoint().length() - 1); if (knownPaths.contains(rel)) { staticHandler.handle(ctx); } else {