From f0a76420b6232b9f8143b0e7066520a4d0f33396 Mon Sep 17 00:00:00 2001 From: Karol Date: Mon, 25 Feb 2019 17:54:55 +0000 Subject: [PATCH] BAEL-2713 Serve Static Content in Spring WebFlux (#6404) --- spring-5-reactive/pom.xml | 22 +++++++++ spring-5-reactive/src/main/assets/index.html | 10 ++++ .../StaticContentApplication.java | 28 +++++++++++ .../staticcontent/StaticContentConfig.java | 35 +++++++++++++ ...lication-assets-custom-location.properties | 3 ++ .../src/main/resources/img/example-image.png | Bin 0 -> 17429 bytes .../src/main/resources/public/index.html | 10 ++++ ...cContentCustomLocationIntegrationTest.java | 39 +++++++++++++++ ...ContentDefaultLocationIntegrationTest.java | 46 ++++++++++++++++++ 9 files changed, 193 insertions(+) create mode 100644 spring-5-reactive/src/main/assets/index.html create mode 100644 spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentApplication.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentConfig.java create mode 100644 spring-5-reactive/src/main/resources/application-assets-custom-location.properties create mode 100644 spring-5-reactive/src/main/resources/img/example-image.png create mode 100644 spring-5-reactive/src/main/resources/public/index.html create mode 100644 spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentCustomLocationIntegrationTest.java create mode 100644 spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentDefaultLocationIntegrationTest.java diff --git a/spring-5-reactive/pom.xml b/spring-5-reactive/pom.xml index a1eb6f4c8a..8d5324a673 100644 --- a/spring-5-reactive/pom.xml +++ b/spring-5-reactive/pom.xml @@ -124,6 +124,28 @@ + + maven-resources-plugin + 3.0.1 + + + copy-resources + validate + + copy-resources + + + + + src/main/assets + true + + + ${basedir}/target/classes/assets + + + + org.springframework.boot spring-boot-maven-plugin diff --git a/spring-5-reactive/src/main/assets/index.html b/spring-5-reactive/src/main/assets/index.html new file mode 100644 index 0000000000..047514df1c --- /dev/null +++ b/spring-5-reactive/src/main/assets/index.html @@ -0,0 +1,10 @@ + + + + + Baeldung: Static Content in Spring WebFlux + + +Example Spring Web Flux and web resources configuration + + \ No newline at end of file diff --git a/spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentApplication.java b/spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentApplication.java new file mode 100644 index 0000000000..31a3de4927 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentApplication.java @@ -0,0 +1,28 @@ +package com.baeldung.staticcontent; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; + +import java.util.Collections; + +@SpringBootApplication +public class StaticContentApplication { + + public static void main(String[] args) { + SpringApplication app = new SpringApplication(StaticContentApplication.class); + app.setDefaultProperties(Collections.singletonMap("server.port", "8084")); + app.run(args); + } + + @Bean + public SecurityWebFilterChain staticContentSpringSecurityFilterChain(ServerHttpSecurity http) { + http.authorizeExchange() + .anyExchange() + .permitAll(); + return http.build(); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentConfig.java b/spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentConfig.java new file mode 100644 index 0000000000..1fbb9958e7 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentConfig.java @@ -0,0 +1,35 @@ +package com.baeldung.staticcontent; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; + +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; +import static org.springframework.web.reactive.function.server.ServerResponse.ok; + +@Configuration +public class StaticContentConfig { + + @Bean + public RouterFunction htmlRouter(@Value("classpath:/public/index.html") Resource html) { + return route( + GET("/"), + request -> ok() + .contentType(MediaType.TEXT_HTML) + .syncBody(html) + ); + } + + @Bean + public RouterFunction imgRouter() { + return RouterFunctions.resources("/img/**", new ClassPathResource("img/")); + } + +} diff --git a/spring-5-reactive/src/main/resources/application-assets-custom-location.properties b/spring-5-reactive/src/main/resources/application-assets-custom-location.properties new file mode 100644 index 0000000000..9a2dbb04d9 --- /dev/null +++ b/spring-5-reactive/src/main/resources/application-assets-custom-location.properties @@ -0,0 +1,3 @@ +# Use in Static content Example +spring.webflux.static-path-pattern = /assets/** +spring.resources.static-locations = classpath:/assets/ \ No newline at end of file diff --git a/spring-5-reactive/src/main/resources/img/example-image.png b/spring-5-reactive/src/main/resources/img/example-image.png new file mode 100644 index 0000000000000000000000000000000000000000..2fa6c7b8c5112fd99c91c94de9f7f5b9e24635aa GIT binary patch literal 17429 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 + + + + Baeldung: Static Content in Spring WebFlux + + +Example HTML file + + \ No newline at end of file diff --git a/spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentCustomLocationIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentCustomLocationIntegrationTest.java new file mode 100644 index 0000000000..f40ff83738 --- /dev/null +++ b/spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentCustomLocationIntegrationTest.java @@ -0,0 +1,39 @@ +package com.baeldung.staticcontent; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; + + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ActiveProfiles("assets-custom-location") +public class StaticContentCustomLocationIntegrationTest { + + @Autowired + private WebTestClient client; + + @Test + public void whenRequestingHtmlFileFromCustomLocation_thenReturnThisFileAndTextHtmlContentType() throws Exception { + client.get() + .uri("/assets/index.html") + .exchange() + .expectStatus().isOk() + .expectHeader().valueEquals(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML_VALUE); + } + + @Test + public void whenRequestingMissingStaticResource_thenReturnNotFoundStatus() throws Exception { + client.get() + .uri("/assets/unknown.png") + .exchange() + .expectStatus().isNotFound(); + } + +} \ No newline at end of file diff --git a/spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentDefaultLocationIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentDefaultLocationIntegrationTest.java new file mode 100644 index 0000000000..820d6e13ef --- /dev/null +++ b/spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentDefaultLocationIntegrationTest.java @@ -0,0 +1,46 @@ +package com.baeldung.staticcontent; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; + + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class StaticContentDefaultLocationIntegrationTest { + + @Autowired + private WebTestClient client; + + @Test + public void whenRequestingHtmlFileFromDefaultLocation_thenReturnThisFileAndTextHtmlContentType() throws Exception { + client.get() + .uri("/index.html") + .exchange() + .expectStatus().isOk() + .expectHeader().valueEquals(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML_VALUE); + } + + @Test + public void whenRequestingPngImageFromImgLocation_thenReturnThisFileAndImagePngContentType() throws Exception { + client.get() + .uri("/img/example-image.png") + .exchange() + .expectStatus().isOk() + .expectHeader().valueEquals(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE); + } + + @Test + public void whenRequestingMissingStaticResource_thenReturnNotFoundStatus() throws Exception { + client.get() + .uri("/unknown.png") + .exchange() + .expectStatus().isNotFound(); + } + +} \ No newline at end of file