From d2728003828215cf49779c161faf7576da569e51 Mon Sep 17 00:00:00 2001 From: Tomas Langer Date: Mon, 15 Aug 2022 13:34:06 +0200 Subject: [PATCH] MP path based static content should use index.html as the default index file --- etc/copyright-exclude.txt | 4 +- .../server/ServerCdiExtension.java | 7 +- tests/integration/mp-gh-4654/pom.xml | 59 ++++++++ .../gh4654/Gh4654StaticContentTest.java | 137 ++++++++++++++++++ .../resources/static/classpath/index.html | 1 + tests/integration/pom.xml | 1 + .../FileSystemContentHandlerTest.java | 20 +-- 7 files changed, 213 insertions(+), 16 deletions(-) create mode 100644 tests/integration/mp-gh-4654/pom.xml create mode 100644 tests/integration/mp-gh-4654/src/test/java/io/helidon/tests/integration/gh4654/Gh4654StaticContentTest.java create mode 100644 tests/integration/mp-gh-4654/src/test/resources/static/classpath/index.html diff --git a/etc/copyright-exclude.txt b/etc/copyright-exclude.txt index 0fae0141c19..3b40ad20e3c 100644 --- a/etc/copyright-exclude.txt +++ b/etc/copyright-exclude.txt @@ -24,7 +24,6 @@ .MD .p12 .txt -.sql jaxb.index /MANIFEST.MF /README @@ -35,6 +34,7 @@ jaxb.index .p12 .bin .vm +.sql src/main/proto/ src/test/resources/keystore/ etc/javadoc/ @@ -55,3 +55,5 @@ target/ META-INF/services/ persistence_3_0.xjb persistence_3_0.xsd +# excluded as this is a test file and we need to validate its content +src/test/resources/static/classpath/index.html diff --git a/microprofile/server/src/main/java/io/helidon/microprofile/server/ServerCdiExtension.java b/microprofile/server/src/main/java/io/helidon/microprofile/server/ServerCdiExtension.java index 919e94c6441..a84b339b620 100644 --- a/microprofile/server/src/main/java/io/helidon/microprofile/server/ServerCdiExtension.java +++ b/microprofile/server/src/main/java/io/helidon/microprofile/server/ServerCdiExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021 Oracle and/or its affiliates. + * Copyright (c) 2018, 2022 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -288,9 +288,10 @@ private void registerPathStaticContent(Config config) { StaticContentSupport.FileSystemBuilder pBuilder = StaticContentSupport.builder(config.get("location") .as(Path.class) .get()); - config.get("welcome") + pBuilder.welcomeFileName(config.get("welcome") .asString() - .ifPresent(pBuilder::welcomeFileName); + .orElse("index.html")); + StaticContentSupport staticContent = pBuilder.build(); if (context.exists()) { diff --git a/tests/integration/mp-gh-4654/pom.xml b/tests/integration/mp-gh-4654/pom.xml new file mode 100644 index 00000000000..deafa7c11f0 --- /dev/null +++ b/tests/integration/mp-gh-4654/pom.xml @@ -0,0 +1,59 @@ + + + + + io.helidon.tests.integration + helidon-tests-integration + 4.0.0-SNAPSHOT + + 4.0.0 + + helidon-tests-integration-mp-gh-4654 + Helidon Tests Integration MP GH 4654 + Reproducer for Github issue #4654 - static content default index + + + + io.helidon.microprofile.server + helidon-microprofile-server + + + io.helidon.webserver + helidon-webserver-test-support + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.hamcrest + hamcrest-all + test + + + \ No newline at end of file diff --git a/tests/integration/mp-gh-4654/src/test/java/io/helidon/tests/integration/gh4654/Gh4654StaticContentTest.java b/tests/integration/mp-gh-4654/src/test/java/io/helidon/tests/integration/gh4654/Gh4654StaticContentTest.java new file mode 100644 index 00000000000..9880272acf9 --- /dev/null +++ b/tests/integration/mp-gh-4654/src/test/java/io/helidon/tests/integration/gh4654/Gh4654StaticContentTest.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2022 Oracle and/or its affiliates. + * + * 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 + * + * http://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 io.helidon.tests.integration.gh4654; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; + +import io.helidon.config.mp.MpConfigSources; +import io.helidon.microprofile.server.Server; +import io.helidon.webserver.testsupport.TemporaryFolder; +import io.helidon.webserver.testsupport.TemporaryFolderExtension; + +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.Response; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.spi.ConfigProviderResolver; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +@ExtendWith(TemporaryFolderExtension.class) +class Gh4654StaticContentTest { + private static Client client; + private TemporaryFolder folder; + private Server server; + private WebTarget target; + + @BeforeAll + static void setupAll() { + client = ClientBuilder.newClient(); + } + + @AfterAll + static void cleanupAll() { + client.close(); + client = null; + } + + @BeforeEach + void setup() throws IOException { + // cannot use @HelidonTest, as the tmp folder extension requires to be run beforeEach + + // root + Path root = folder.root().toPath(); + Files.writeString(root.resolve("index.html"), "Root Index HTML"); + Files.writeString(root.resolve("foo.txt"), "Foo TXT"); + // css + Path cssDir = folder.newFolder("css").toPath(); + Files.writeString(cssDir.resolve("a.css"), "A CSS"); + // bar + Path other = folder.newFolder("other").toPath(); + Files.writeString(other.resolve("index.html"), "Other Index"); + + ConfigProviderResolver cpr = ConfigProviderResolver.instance(); + Config config = cpr.getBuilder() + .withSources(MpConfigSources.create(Map.of( + "server.host", "localhost", + "server.port", "0", + "server.static.path.location", folder.root().getAbsolutePath(), + "server.static.path.context", "/static", + "server.static.classpath.location", "/static", + "server.static.classpath.context", "/static" + ))) + .build(); + cpr.registerConfig(config, null); + + server = Server.create() + .start(); + + target = client.target("http://localhost:" + server.port() + "/static"); + + } + + @AfterEach + void cleanup() { + server.stop(); + target = null; + } + + @ParameterizedTest(name = "\"{0}\" - {2}") + @CsvSource({ + "/,Root Index HTML,path should serve index.html", + "/index.html,Root Index HTML,path should serve index.html", + "/foo.txt,Foo TXT,path should serve foo.txt", + "/css/a.css,A CSS,path should serve css/a.css", + "/other,Other Index,path should serve other/index.html", + "/other/index.html,Other Index,path should serve other/index.html", + "/classpath,classpath index,classpath should serve index.html", + "/classpath/index.html,classpath index,classpath should serve index.html" + }) + void testExists(String path, String expectedContent, String name) { + Response response = target.path(path) + .request() + .get(); + + assertThat(response.getStatus(), is(200)); + assertThat(response.readEntity(String.class), is(expectedContent)); + } + + @ParameterizedTest(name = "{0}") + @CsvSource({ + "/not-there.txt", + "/css/not-there.txt", + "/classpath/not-there.txt" + }) + void test404(String path) { + Response response = target.path(path) + .request() + .get(); + + assertThat(response.getStatus(), is(404)); + } +} diff --git a/tests/integration/mp-gh-4654/src/test/resources/static/classpath/index.html b/tests/integration/mp-gh-4654/src/test/resources/static/classpath/index.html new file mode 100644 index 00000000000..5631ed03720 --- /dev/null +++ b/tests/integration/mp-gh-4654/src/test/resources/static/classpath/index.html @@ -0,0 +1 @@ +classpath index \ No newline at end of file diff --git a/tests/integration/pom.xml b/tests/integration/pom.xml index 20da14408d2..defb4a59b30 100644 --- a/tests/integration/pom.xml +++ b/tests/integration/pom.xml @@ -49,6 +49,7 @@ mp-gh-3246 mp-gh-3974 mp-gh-4123 + mp-gh-4654 kafka jms config diff --git a/webserver/static-content/src/test/java/io/helidon/webserver/staticcontent/FileSystemContentHandlerTest.java b/webserver/static-content/src/test/java/io/helidon/webserver/staticcontent/FileSystemContentHandlerTest.java index 5784ef54608..d90236a3f50 100644 --- a/webserver/static-content/src/test/java/io/helidon/webserver/staticcontent/FileSystemContentHandlerTest.java +++ b/webserver/static-content/src/test/java/io/helidon/webserver/staticcontent/FileSystemContentHandlerTest.java @@ -43,7 +43,7 @@ * Tests {@link io.helidon.webserver.staticcontent.FileSystemContentHandler}. */ @ExtendWith(TemporaryFolderExtension.class) -public class FileSystemContentHandlerTest { +class FileSystemContentHandlerTest { private TemporaryFolder folder; @@ -51,15 +51,15 @@ public class FileSystemContentHandlerTest { public void createContent() throws IOException { // root Path root = folder.root().toPath(); - Files.write(root.resolve("index.html"), "Index HTML".getBytes(StandardCharsets.UTF_8)); - Files.write(root.resolve("foo.txt"), "Foo TXT".getBytes(StandardCharsets.UTF_8)); + Files.writeString(root.resolve("index.html"), "Index HTML"); + Files.writeString(root.resolve("foo.txt"), "Foo TXT"); // css Path cssDir = folder.newFolder("css").toPath(); - Files.write(cssDir.resolve("a.css"), "A CSS".getBytes(StandardCharsets.UTF_8)); - Files.write(cssDir.resolve("b.css"), "B CSS".getBytes(StandardCharsets.UTF_8)); + Files.writeString(cssDir.resolve("a.css"), "A CSS"); + Files.writeString(cssDir.resolve("b.css"), "B CSS"); // bar Path other = folder.newFolder("other").toPath(); - Files.write(other.resolve("index.html"), "Index HTML".getBytes(StandardCharsets.UTF_8)); + Files.writeString(other.resolve("index.html"), "Index HTML"); } static String responseToString(TestResponse response) @@ -71,8 +71,7 @@ static String responseToString(TestResponse response) } @Test - public void serveFile() throws Exception { - try { + void serveFile() throws Exception { Routing routing = Routing.builder() .register("/some", StaticContentSupport.create(folder.root().toPath())) .build(); @@ -105,13 +104,10 @@ public void serveFile() throws Exception { .path("/some/css/") .get(); assertThat(response.status(), is(Http.Status.NOT_FOUND_404)); - } catch(Throwable ex){ - ex.printStackTrace(); - } } @Test - public void serveIndex() throws Exception { + void serveIndex() throws Exception { Routing routing = Routing.builder() .register(StaticContentSupport.builder(folder.root().toPath()) .welcomeFileName("index.html")